【问题标题】:.Net : Do static constructors get called when a constant is access?.Net:访问常量时是否调用静态构造函数?
【发布时间】:2011-09-13 02:09:32
【问题描述】:

这就是我的想法......

public class MyClass
{
    public const string MyConstant = "MyConstantValue";

    private static MyClass DefaultInstance;

    static MyClass()
    {
         DefaultInstance = new MyClass();
    }
}

...

NotificationService.RegisterForNotification(MyClass.MyConstant, Callback);

这会起作用还是我需要使用类似static readonly property 字段来触发静态构造函数?

【问题讨论】:

    标签: c# static static-constructor


    【解决方案1】:

    使用常量并不一定会导致调用静态构造函数的成员访问。允许编译器(鼓励,甚至)在编译时替换常量的值。

    您建议的static readonly 解决方法应该没问题,尽管readonly 建议的是一个字段,而不是一个属性。属性在没有 setter 时为只读,不涉及 readonly 关键字。

    一个简单的例子:

    class HasSConstructor
    {
        internal const int Answer = 42;
        static HasSConstructor()
        {
            System.Console.WriteLine("static constructor running");
        }
    }
    
    public class Program
    {
        public static void Main()
        {
            System.Console.WriteLine("The answer is " + HasSConstructor.Answer.ToString());
        }
    }
    

    .NET 4.0 下的输出:

    答案是 42

    静态构造函数永远不会运行!

    【讨论】:

    • 您对属性/字段注释是正确的,我大多数时候倾向于不区分,这可能会让我在这些日子里遇到麻烦。
    【解决方案2】:

    在创建第一个实例或引用任何静态成员之前,会自动调用静态构造函数。见这里:MSDN: Static Constructors

    顺便说一句,常量字段本质上是静态的,但正如所指出的,它们可能(并且可能会)被值本身替换。

    【讨论】:

    • 它是“立即之前”。具有静态构造函数的 C# 类永远不会标记为beforefieldinit。但是使用常量(在 .NET 中称为 literal)不会访问静态成员。
    【解决方案3】:

    如果您只是访问公共常量,则不会调用静态构造函数。例如,考虑这个类:

    class Testo
    {
        public const string MyValue = "Hello, world";
        public static readonly int xyzzy;
    
        static Testo()
        {
            Console.WriteLine("In static constructor");
            xyzzy = 27;
        }
    }
    

    现在,在另一个类中,执行:

    Console.WriteLine(Testo.MyValue);
    Console.WriteLine(Testo.xyzzy);
    

    您的输出将是:

    Hello, world
    In static constructor
    27
    

    在编译时从类中提升常量。所以Testo.MyValue 的值在运行时不会引用Testo 类。在调用需要初始化的东西之前,不会调用静态构造函数。

    所以,是的,如果你想确保构造函数被调用,你需要访问 static readonly 之类的东西。

    【讨论】:

      【解决方案4】:

      不,你不需要这样的。加载类时调用静态构造函数。

      【讨论】:

      • 是的,什么时候加载一个类?
      • 要么存在对该类的引用(例如访问静态成员、实例化对象、强制转换为该类),要么您手动加载该类。
      • @Nam:这不对。如果类型未标记beforefieldinit,并且具有静态构造函数的C# 类未标记beforefieldinit,则不允许强制转换或手动加载类运行类型初始化程序。跨度>
      • 如何手动加载类?并且强制转换不一定调用静态构造函数:public static explicit operator Foo(Bar bar){ return null; }。调用这个演员不会。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-07
      • 2013-01-11
      • 1970-01-01
      相关资源
      最近更新 更多