好的,让我们仔细检查一下。我们有
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)
我们有一个 type 的参数List<T>
和一个 type 的形参IEnumerable<V>
。List<T>
实现IEnumerable<T>
所以我们推断V是T。
好的,所以我们的候选列表现在包括:
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)
我们有一个 type 的参数IEnumerable<T>
,所以我们推断第二个和第三个是:
Update(IEnumerable<T> entities)
Update<IEnumerable<T>>(IEnumerable<T> entity)
Update<T>(IEnumerable<T> entities)
现在我们有了三个具有相同参数列表的适用候选。那些正在建设中的自然会比自然的更糟糕,所以我们消除了第二个和第三个,只留下第一个。它赢了,它没有被违反的限制。
删除第三种方法也可以
您的陈述是错误的;这将产生与第一种情况相同的错误。带走第三位候选人不会导致第一位候选人突然开始击败第二位候选人。