接收List的C#泛型方法不会为实际类型的T调用重载方法(更喜欢通用
参见英文答案 >
why is this generic not resolved at compile time?????????????????????????????????????4个
我有这个例子C#代码: class Stuff { } // empty class void Main() { var list = new List<Stuff> { new Stuff(),new Stuff() }; Fun(list); } void Fun<T>(List<T> a) { Debug.Log("called List<T> Fun"); foreach (T t in a) { Fun(t); } } void Fun(Stuff a) { Debug.Log("called Stuff Fun"); } void Fun<T>(T a) { Debug.Log("called T Fun"); } 调用Main()最终打印: called List<T> Fun called T Fun called T Fun 我不明白为什么编译器能够按预期调用Fun< T>(List< T> a),但后来不知道调用Fun(Stuff a),这比Fun< T>(T更具体)一个).在这种情况下,在编译时是否确定T是Stuff?在Fun< T>(List< T> a)中打印typeof(T)给出了“Stuff”如预期的那样,但这不是任何事情的证据…… 添加Fun(List< Stuff> a)方法有效但不可取(项目中列表有许多不同的可能类型,并且所有这些行为都应该相同). 我试过搜索这个问题,但无法用我能找到它的方式来表达它.对不起,如果之前有人问过这个问题(可能!). 解决方法
关键是要理解void Fun< T>(List< T> a)被编译一次,重载决议执行一次.不是每T一次,而是一次.
在编译此代码时考虑编译器的情况: void Fun<T>(List<T> a) { Debug.Log("called List<T> fun"); foreach (T t in a) { Fun(t); } } 特别是,考虑Fun(t)调用中的重载决策. 编译器对T一无所知,这是Fun(t)调用中参数的类型 – 它可以是任何非指针类型.它必须在这些签名之间执行重载解析: void Fun<T>(List<T> a) void Fun(Stuff a) void Fun<T>(T a) 这些方法中唯一适用的是最后一个 – 调用代码中的T用作我们调用的方法中T的类型参数,并且没问题.其他两种方法不适用,因为没有从T到List< TList>的转换. (对于任何TList),或从T到Stuff. 如果您希望在执行时执行重载决策,则可以使用动态类型: foreach (dynamic d in a) { Fun(d); } 我个人并不喜欢这样做,但在这种情况下它可能会做你想要的.另一方面,对于嵌套列表,它可能会变得棘手 – 如果你是一个List< int>,那么你期望它调用Fun< List< int>>(list)或Fun< int>(list)?老实说,我不记得规则,知道哪些是“更好”或是否含糊不清. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |