C#:继承过程中的静态成员
程序员文章站
2022-03-10 18:27:44
在知乎上看到一个关于“泛基“的实现,感觉挺有意思,想试试效果,代码如下: 先忽略这段代码的作用,重点是运行后控制台没有任何输出。跟踪一下发现根本没有走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 = ""; } }
以上、欢迎交流指正。如有侵权,请联系作者删除。