昨天在我的隨筆My god!!屬性可以變成方法!!中提到,一個類繼承一個類的屬性,然後可以使用new方法使用一個方法覆蓋掉此屬性,這讓我覺得詫異。在回複中有部分人是這樣理解這種現象的,屬性在中繼語言時也被翻譯成了方法。
我重新寫了一個類
public class ClassA
{
private string a="ClassA A";
//屬性
public string A
{
get
{
return a;
}
set
{
a=value;
}
}
//欄位
public string B="ClassA B";
//方法
public string C()
{
return "ClassA C";
}
//重載的方法
public string D()
{
return "ClassA D";
}
public string D(string arr)
{
return "Hello"+arr;
}
}
我們用ildasm開啟產生的檔案,
的確A的屬性訪問器被編譯成了Set_A和Get_A方法。似乎我們已經找到了此問題的答案。
但是請你看下面的代碼,事實將推翻此理論
public class ClassB:ClassA
{
//A是一個屬性,我用方法隱藏它
new public string A()
{
return "ClassB A";
}
//B是一個欄位,我用方法隱藏它
new public string B()
{
return "ClassB B";
}
//C是一個方法,我用欄位隱藏它
new public string C="ClassB C";
//D是一個重載了的方法,我用一個欄位隱藏它
new public string D="ClassB D";
}
你覺得這樣的代碼編譯能通過嗎,或者編譯會出現警告嗎??答案卻是這段代碼編譯通過而且沒有任何錯誤提示。
結論:屬性和欄位和方法(不管傳回值),可以使用任何同名的屬性或欄位或方法隱藏。帶參數的方法可以用參數簽名相同的方法隱藏。一批重載的方法只需要一個欄位或屬性可全部隱藏。
PS:如果把類B中的成員換成private或protected則覆蓋不能起到效果,訪問時需訪問父類成員。
最後:感覺使用new關鍵字進行隱藏的時候情況十分複雜,建議採用同類型成員進行隱藏,屬性隱藏屬性,方法隱藏方法,以免給編程帶來不必要的麻煩。