好的,我們仔細研究一下。我們有
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