C#編譯器中發生了什麼情況,導致以下模糊調用編譯錯誤?爲什麼編譯器在傳遞繼承類型時會出現模糊的調用錯誤?
同樣的問題適用於擴展方法,或者TestClass
是通用的並且使用實例而不是靜態方法。我知道它很容易解決(例如,在方法調用上投下secondInstance
到Test1
),但我更好奇編譯器應用什麼邏輯來選擇方法。
我的假設是,編譯器在方法檢測上應用一些特定性度量(比如CSS)來確定最具體的匹配 - 這是無效的嗎?
class Type1 { }
class Type2 : Type1 {}
class TestClass
{
public static void Do<T>(T something, object o) where T : Type1
{}
public static void Do(Type1 something, string o)
{}
}
void Main()
{
var firstInstance = new Type1();
TestClass.Do(firstInstance, new object()); // Calls Do<T>(T, obj)
TestClass.Do(firstInstance, "Test"); // Calls Do(Type1, string)
var secondInstance = new Type2();
TestClass.Do(secondInstance, new object()); // Calls Do<T>(T, obj)
TestClass.Do(secondInstance, "Test"); // "The call is ambiguous" compile error
}
//編輯:邁克ž提出我已經解釋爲被用作用於方法選擇的權重的「鑄距離」的概念。對此的測試似乎支持(儘管我不確定Type-> Generic Type是如何加權的)。
// Add the following two methods to TestClass
public static void Do<T>(T something) where T : Type1
{}
public static void Do(Type1 something)
{}
public static void Do<T>(T something, object o) where T : Type1
{}
public static void Do(Type1 something, string o)
{}
void Main()
{
var firstInstance = new Type1();
// Can't select string
TestClass.Do(firstInstance, new object()); // Calls Do<T>(T, obj)
// Do() distance is 0, Do<T> distance is 1
TestClass.Do(firstInstance, "Test"); // Calls Do(Type1, string)
// Do() distance is 0, Do<T> distance is ? (but more than 0?)
TestClass.Do(firstInstance); // Calls Do(Type1)
var secondInstance = new Type2();
// Can't select string
TestClass.Do(secondInstance, new object()); // Calls Do<T>(T, obj)
// Do() distance is 1, Do<T> distance is 1
TestClass.Do(secondInstance, "Test"); // "The call is ambiguous" compile error
// Do() distance is 1, Do<T> distance is ? (but less than 1?)
TestClass.Do(secondInstance); // Calls Do<T>(T)
}
它不知道選擇哪個'Do',因爲字符串也是一個對象。你可以切換你的參數順序,或者在調用時更明確'做' –
Dweeberly
當第一個參數顯式爲'Type1'時,它設法確定'string'比'object'更具體,但是當第一個參數繼承'Type1' –
我會盡量避免這種情況。如果您沒有將通用方法命名爲非通用方法,那麼可以避免大量混淆。同樣適用於btw類。 – PMF