繼承時,用new修飾詞的陷阱,覆寫property時的錯誤

有一次寫Code時,因為要寫泛型與非泛型的類別,為了多型所以泛型繼承非泛型,在將其中要泛型的property用new覆寫,可是執行實一直發生NullReferenceException,追縱下原來是用錯了property自動實作寫法,而且沒想到前幾天我的同事也跟我犯了同樣的錯誤。

有一次寫Code時,因為要寫泛型與非泛型的類別,為了多型所以泛型繼承非泛型,在將其中要泛型的property用new覆寫,可是執行實一直發生NullReferenceException,追縱下原來是用錯了property自動實作寫法,而且沒想到前幾天我的同事也跟我犯了同樣的錯誤。


public class BaseClass
{
    public object Property { get; set; }
}

public class GenericClass<T> : BaseClass
{
    public new T Property { get; set; }
}

 

執行結果

image

為什麼會發生這樣的問題,要從property {get;set;}說起,property {get;set;}是C# 3.0增加的自動實作屬性語法,編譯後會產生自動產生 private field


//簡寫
public object Property { get; set; }
//編譯後會變成如下
private object propertyField;

public object Property
{
    get
    {
        return propertyField;
    }
    set
    {
        propertyField = value;
    }
}

所以BaseClass與GenericClass編譯後都是存取不同的Field,加上new修飾詞來隱藏繼承自基底類別的成員,所以GenericClass在本身型別與轉成基底類別,同樣存取Property,但是對CLR來說確是存取不同的屬性,所以才會發生對同一個實例不同型別存取屬性,有不同結果的錯誤。

 

正確的寫法


//BaseClass不變
public class BaseClass
{
    public object Property { get; set; }
}

//改成存取BaseClass
public class GenericClass<T> : BaseClass
{
    public new T Property
    {
        get
        {
            return (T)base.Property;
        }
        set
        {
            base.Property = value;
        }
    }
}

 

參考資料