2011-12-10 42 views
3

我遇到了一個我沒有想到的重載解析問題。顯然,編譯器相當於解析了對MyPrint方法的調用,將"Hello world"傳遞給派生類中的MyPrint<T>(T : struct),而不是在基類中定義的MyPrint(string)。由於解析器選擇的方法不接受字符串,所以我得到一個編譯器錯誤。重載解決方案選擇不兼容的泛型方法而不是兼容的基類方法

我想它與脆性基類問題有關,如Jon Skeet wrote in his bookEric Lippert on his blog。 Lippert引用標準如下:

如果衍生的 類中的任何方法適用,則基類中的方法不是候選方法。

但是我沒有看到派生類中的任何方法都適用,編譯器也不從錯誤中判斷。我想知道兩件事情:爲什麼它以這種方式工作,我如何讓C#做我想讓它再做的事情?

人爲的例子證明了問題:

class Program 
{ 
    static void Main(string[] args) 
    { 
     Derived d = new Derived(); 

     d.MyPrint(10); 

     // ERROR: The type 'string' must be a non-nullable value type 
     // in order to use it as parameter 'T' 
     // in the generic type or method 'Derived.MyPrint<T>(T)'. 
     d.MyPrint("Hello world!"); 
    } 
} 

class Base 
{ 
    // I print only strings. 
    public void MyPrint(string value) 
    { 
     Console.WriteLine("String: " + value); 
    } 
} 

class Derived : Base 
{ 
    // I print any primitive type, enums and DateTime, 
    // but NOT string (since that is not a value type). 
    public void MyPrint<T>(T value) 
     where T : struct, IConvertible 
    { 
     Console.WriteLine("IConvertible: " + value.ToString()); 
    } 
} 
+2

MyPrint 在重載解析期間看起來像MyPrint ,然後因爲未滿足約束而稍後失敗。 「約束不是簽名的一部分」的結果,我想 – harold

+0

這將是一個好回答,而不是評論 –

+0

@SebastianPiu好,完成 – harold

回答

2

你已經找到一半的原因,但你也需要Constraints are not part of the signature.結合「如果派生類中的任何方法適用,基類中的方法不是候選者」,那麼在重載解析期間,您會得到兩種方法:看起來像MyPrint(string),因此是適用的,所以選擇派生最多的類中的一個。只有在這之後檢查了約束,然後失敗。

0

你可以把它的工作,如果你在你的派生類中定義的:

public new void MyPrint(string value) 
{ 
    base.MyPrint(value); 
} 

至於「爲什麼」,對不起,我不」不知道。可能C# Language Specification可以幫助回答這個問題。

相關問題