欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

输出如下:

C#:继承过程中的静态成员

目前为止可以得出两个结论:

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

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