在知乎上看到一個關於“泛基“的實現,感覺挺有意思,想試試效果,代碼如下: 先忽略這段代碼的作用,重點是運行後控制台沒有任何輸出。跟蹤一下發現根本沒有走MyClass(),DataForThisType的值一直是null。關於靜態構造方法,網上的解釋是: 通常情況下:最先調用基類的構造方法,但如果該類 ...
在知乎上看到一個關於“泛基“的實現,感覺挺有意思,想試試效果,代碼如下:
public abstract class MyBase<T> where T : MyBase<T> { public static string DataForThisType { get; set; } public static T Instance { get; protected set; } public static readonly IReadOnlyDictionary<string, MemberInfo> Members = typeof(T).GetMembers().ToDictionary(x => x.Name); } public class MyClass : MyBase<MyClass> { static MyClass() { DataForThisType = string.Format("MyClass got {0} members", Members.Count); Instance = new MyClass(); } }
class Program { static void Main(string[] args) { Console.Write(MyClass.DataForThisType); Console.WriteLine(); Console.ReadLine(); } }
先忽略這段代碼的作用,重點是運行後控制台沒有任何輸出。跟蹤一下發現根本沒有走MyClass(),DataForThisType的值一直是null。關於靜態構造方法,網上的解釋是:
- 通常情況下:最先調用基類的構造方法,但如果該類有靜態構造方法,且首次調用該類,則先調用該類的靜態構造方法,再調用其基類的靜態構造方法。
Child.Static->Super.Static->Super.Instance->Child Instance - 靜態構造方法是.net調用的,在創建第一個實例或者靜態成員被引用時,.net將自動調用靜態構造方法來初始化類。
這就有問題了,MyClass的靜態構造方法不僅沒被優先調用,甚至全程都沒有被調用。難道上述這個說法是錯的?為了排除干擾,給上述代碼簡化一下
class Program { static void Main(string[] args) { Console.Write(TestChild.StaticPropertyBase); Console.WriteLine(); Console.ReadLine(); } } public class TestBase { public static string StaticPropertyBase { get; protected set; } } public class TestChild : TestBase { static TestChild() { StaticPropertyBase = typeof(TestChild) + ":" + "StaticPropertyBase"; } }
運行結果還是一樣,沒有輸出,TestChild的靜態構造沒被執行。回頭再來看靜態構造方法的調用條件:在創建第一個實例或者靜態成員被引用時!!!實例是肯定沒有的,但
是我有引用靜態成員啊..等等,我引用的好像是父類的靜態成員,難道父類的靜態成員不行?說好的繼承全部家產呢?那就再來試試,給TestChild聲明一個自己的靜態屬性。
class Program { static void Main(string[] args) { Console.Write(TestChild.StaticPropertyChild); Console.WriteLine(); Console.Write(TestChild.StaticPropertyBase); Console.WriteLine(); Console.Write(TestBase.StaticPropertyBase); Console.WriteLine(); Console.ReadLine(); } } public class TestBase { public static string StaticPropertyBase { get; protected set; } } public class TestChild : TestBase { public static string StaticPropertyChild { get; set; } static TestChild() { StaticPropertyBase = typeof(TestChild) + ":" + "StaticPropertyBase"; StaticPropertyChild = "StaticPropertyChild"; } }
輸出如下:
目前為止可以得出兩個結論:
1)想觸發一個類的靜態構造方法?要麼實例化它,要麼訪問它的靜態成員,訪問它基類的的靜態成員是不行的。
2)靜態成員的繼承其實並不是真正的繼承,或者說根本就無法繼承,只是訪問父類的靜態成員而已。但與實例成員不同的是,用protected修飾的靜態成員
可以在其派生類中訪問,但用protected修飾的非靜態成員,則不可訪問。下麵代碼體會一下,new TestBase().hh =" ";這句報錯。
public class TestBase { public static string StaticPropertyBase { get; protected set; } public string hh { get; protected set; } } public class TestChild : TestBase { public static string StaticPropertyChild { get; set; } static TestChild() { StaticPropertyBase = typeof(TestChild) + ":" + "StaticPropertyBase"; StaticPropertyChild = "StaticPropertyChild"; } TestChild() { hh = ""; new TestBase().hh = ""; } }
以上、歡迎交流指正。如有侵權,請聯繫作者刪除。