有一次寫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; }
}
執行結果
為什麼會發生這樣的問題,要從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;
}
}
}