好的,我们仔细研究一下。我们有
Update(new List<T>());
而三位候选人 - 注意,我们只关心签名的考生,所以我们将剥去的返回类型和限制,这是未签名的一部分:
Update(IEnumerable<T> entities)
Update<U>(U entity)
Update<V>(IEnumerable<V> entities)
我们的首要任务是做类型推断这些最后两个人选。如果推论失败,那么他们不适用。
考虑第二种方法
Update<U>(U entity)
我们List<T>
类型的参数和形式参数U
。因此我们推断U
是List<T>
。
考虑第三种方法:
Update<V>(IEnumerable<V> entities)
我们List<T>
类型的参数和IEnumerable<V>
类型的形式参数。 List<T>
实现IEnumerable<T>
因此我们推断,V是T.
OK,所以我们的候选人名单目前包括:
Update(IEnumerable<T> entities)
Update<List<T>>(List<T> entity)
Update<T>(IEnumerable<T> entities)
是否所有这些候选人适用的?是。在每种情况下,List<T>
都可以转换为正式的参数类型。我们无法消除其中的任何一个。
既然我们只有适用的候选人,我们必须确定哪一个是唯一最好的。
我们可以立即消除第三个。第三个和第一个在它们的形式参数列表中是相同的。 C#的规则是当你在形式参数列表中有两个相同的方法时,其中一个“自然地”到达那里,其中一个通过类型替换到达那里,被替换的那个丢失。
我们也可以消除第一个。显然,第二个中的精确匹配比第一个中的精确匹配要好。
这留下第二个人作为最后一个人站立。它赢得重载分辨率的战斗。然后在最终验证期间,我们发现违反了约束条件:List<T>
不保证是派生类T
。
因此重载解析失败。你的论点导致选择的最好的方法是无效的。
如果我打电话Update((new List<T>() { entity }).AsEnumerable())
,它会没事的。
正确的。再次通过它。三名候选人:
Update(IEnumerable<T> entities)
Update<U>(U entity)
Update<V>(IEnumerable<V> entities)
我们IEnumerable<T>
类型的参数,所以我们推断第二和第三个是:
Update(IEnumerable<T> entities)
Update<IEnumerable<T>>(IEnumerable<T> entity)
Update<T>(IEnumerable<T> entities)
现在我们有相同的参数列出了三个候选人适用。那些在建的地方自然比自然地方差,所以我们排除了第二和第三,只剩下第一个。它赢了,它没有任何限制被侵犯。
过,当你删除第三个方法
你的说法是错误的马上就好了;这将产生与第一种情况相同的错误。将第三位候选人取走不会导致第一位候选人突然开始击败第二位候选人。
您闯入了C#规范的黑暗部分 - 重载分辨率。结合泛型,'params',继承,多态性,通用约束,'dynamic',可选参数 - 使我的听力率提高http://msdn.microsoft.com/en-us/library/aa691336(v=vs.71 )的.aspx。 +1为好问题btw – 2013-03-22 10:50:26