C#:继承过程中的静态成员
在知乎上看到一個關于“泛基“的實現,感覺挺有意思,想試試效果,代碼如下:
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 =" ";這句報錯。
? ? ?報錯的原因描述有誤:實則是因為在一個實例中訪問了另一個實例的protected成員,與是否是基類的實例無關
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 = "";}}以上、歡迎交流指正。如有侵權,請聯系作者刪除。
?
轉載于:https://www.cnblogs.com/nevermore-wd/p/8569267.html
總結
以上是生活随笔為你收集整理的C#:继承过程中的静态成员的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java实现字母的大小写转换
- 下一篇: c# char unsigned_dll