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 = "";
        }
    }

以上、欢迎交流指正。如有侵权,请联系作者删除。

 

posted on 2018-03-14 18:13  洞春香酒肆  阅读(2574)  评论(3编辑  收藏  举报

导航