Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/335.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何运行静态构造函数?_C#_.net_Static Constructor - Fatal编程技术网

C# 如何运行静态构造函数?

C# 如何运行静态构造函数?,c#,.net,static-constructor,C#,.net,Static Constructor,我希望在不创建实例的情况下执行类的静态构造函数(即,我希望“加载”该类)。我该怎么做 附加问题:在.NET4和旧版本之间有什么区别吗 编辑: 这个类不是静态的 我希望在创建实例之前运行它,因为它需要一段时间才能运行,并且我希望在第一次访问时避免这种延迟 静态ctor初始化私有静态只读字段,因此不能在方法中运行 静态构造函数在您第一次访问类时自动运行。没有必要(或能力)自己“运行”它。没有必要这样做,a的全部要点是,当类在首次访问时被初始化时,它只运行一次。如果您想按需运行某些东西,那么可以考虑

我希望在不创建实例的情况下执行类的静态构造函数(即,我希望“加载”该类)。我该怎么做

附加问题:在.NET4和旧版本之间有什么区别吗

编辑:

  • 这个类不是静态的
  • 我希望在创建实例之前运行它,因为它需要一段时间才能运行,并且我希望在第一次访问时避免这种延迟
  • 静态ctor初始化
    私有静态只读
    字段,因此不能在方法中运行

静态构造函数在您第一次访问类时自动运行。没有必要(或能力)自己“运行”它。

没有必要这样做,a的全部要点是,当类在首次访问时被初始化时,它只运行一次。如果您想按需运行某些东西,那么可以考虑将初始化代码添加到由构造函数调用的公共方法中。然后,您可以随时调用此方法。但我不确定您为什么要这样做?

正如其他人所说,静态构造函数会自动运行。如果你需要显式的,也许你应该把它重构成一个可以显式运行的静态方法

当然,显式调用静态方法也可以确保静态构造函数已经执行

编辑


静态构造函数在运行时。您只需创建一个名为
initialize
的伪方法,该方法除了确保框架调用静态构造函数外,什么都不做。

只需引用一个静态字段。这将强制运行静态初始化代码。例如:

public class MyClass
{
    private static readonly int someStaticField;

    static MyClass() => someStaticField = 1;

    // any no-op method call accepting your object will do fine
    public static void TouchMe() => GC.KeepAlive(someStaticField);
}
用法:

// initialize statics
MyClass.TouchMe();
每当发生下列情况之一时,将调用cctor(静态构造函数)

  • 您将创建该类的一个实例
  • 可以访问任何静态成员
  • 在此之前的任何时间,如果已设置
  • 如果您想要显式地调用cctor,假设您有其他静态成员,只需调用/访问它们


    如果您在cctor中没有做任何有趣的事情,编译器可能会决定将其标记为
    BeforeFieldInit
    ,这将允许CLR选择提前执行cctor。这里将对此进行更详细的解释:

    其他答案都很好,但是如果您需要强制类构造函数在不引用类型(即反射)的情况下运行,则可以使用:


    访问静态方法时,并不总是调用静态构造函数

    我注意到,如果在基类中调用静态方法,则不会调用超类的静态构造函数。这种意外的行为已经被多次攻击。

    扩展Fábio,以下简短完整的测试程序暴露了JIT敏感的行为细节,将.NET 3.5与最新版本(截至2017年底).NET 4.7.1进行比较,并且还演示了每个版本本身内部构建类型变化的潜在危险。[1]

    下面是以{x86,x64}{Debug,Release}的所有组合运行此程序的控制台输出。我手动添加了一个delta符号
    Δ
    (不是程序发出的),以突出显示两个.NET版本之间的差异

    .NET 2.0/3.5

    2.0.50727.8825 x86调试

    2.0.50727.8825 x86调试TouchMe fieldinit

    2.0.50727.8825 x86发行版fieldinit

    2.0.50727.8825 x86发行版TouchMe fieldinit

    2.0.50727.8825 x64调试

    2.0.50727.8825 x64调试TouchMe fieldinit

    2.0.50727.8825 x64版本

    2.0.50727.8825 x64发布TouchMe fieldinit

    .NET 4.7.1

    4.7.2556.0 x86调试

    4.7.2556.0 x86调试TouchMe fieldinit

    4.7.2556.0 x86版本Δ

    4.7.2556.0 x86发行版TouchMeΔ

    4.7.2556.0 x64调试

    4.7.2556.0 x64调试TouchMe fieldinit

    4.7.2556.0 x64版本

    4.7.2556.0 x64释放触摸板Δ

    如简介中所述,可能比2.0/3.5版本与4.7Delta版本更有趣的是当前.NET版本中的差异,因为它们表明,尽管现在的
    x86
    x64
    之间的字段初始化行为比过去更加一致,但在您的
    Debug
    Release
    版本之间的运行时字段初始化行为仍然可能存在显著差异

    语义将取决于您是否碰巧在类上调用了不相交或看似无关的静态方法,因此如果这样做会给您的总体设计带来bug,那么它可能非常神秘,并且很难找到


    注释
    1。上述程序使用以下实用程序功能显示当前的CLR版本:

    static String clrver()
    {
        var s = typeof(Uri).Assembly.Location;
        return FileVersionInfo.GetVersionInfo(s).ProductVersion.PadRight(14) +
            (IntPtr.Size == 4 ? " x86 " : " x64 ") +
    #if DEBUG
            "Debug  ";
    #else
            "Release";
    #endif
    }
    
    您也可以这样做:

    type.TypeInitializer.Invoke(null, null);
    

    我不太确定您的用例是什么,但您可以使用分部类和内部类强制静态初始值设定项以相当粗糙的方式运行:

    
    public partial class OutterClass
    {
        // When OutterClass is initialized, this will force InnerClass1 to be initialized.
        private static int _innerClass1Touched = InnerClass1.TouchMe;
    
        public static class InnerClass1
        {
            public static int TouchMe = 0;
    
            static InnerClass1()
            {
                Console.WriteLine("InnerClassInitialized");
            }
        }
    }
    
    public partial class OutterClass
    {
        // When OutterClass is initialized, this will force InnerClass2 to be initialized.
        private static int _innerClass2Touched = InnerClass2.TouchMe;
    
        public static class InnerClass2
        {
            public static int TouchMe = 0;
    
            static InnerClass2()
            {
                Console.WriteLine("InnerClass2Initialized");
            }
        }
    }
    
    其思想是使用一个局部outter类和一个访问内部类上另一个静态字段的静态字段。 当outter类静态初始化时,静态字段初始化将启动所有内部类的静态初始化:

    
    public partial class OutterClass
    {
        // When OutterClass is initialized, this will force InnerClass1 to be initialized.
        private static int _innerClass1Touched = InnerClass1.TouchMe;
    
        public static class InnerClass1
        {
            public static int TouchMe = 0;
    
            static InnerClass1()
            {
                Console.WriteLine("InnerClassInitialized");
            }
        }
    }
    
    public partial class OutterClass
    {
        // When OutterClass is initialized, this will force InnerClass2 to be initialized.
        private static int _innerClass2Touched = InnerClass2.TouchMe;
    
        public static class InnerClass2
        {
            public static int TouchMe = 0;
    
            static InnerClass2()
            {
                Console.WriteLine("InnerClass2Initialized");
            }
        }
    }
    
    然后,在应用程序的早期,您只需要参考
    
    public partial class OutterClass
    {
        // When OutterClass is initialized, this will force InnerClass1 to be initialized.
        private static int _innerClass1Touched = InnerClass1.TouchMe;
    
        public static class InnerClass1
        {
            public static int TouchMe = 0;
    
            static InnerClass1()
            {
                Console.WriteLine("InnerClassInitialized");
            }
        }
    }
    
    public partial class OutterClass
    {
        // When OutterClass is initialized, this will force InnerClass2 to be initialized.
        private static int _innerClass2Touched = InnerClass2.TouchMe;
    
        public static class InnerClass2
        {
            public static int TouchMe = 0;
    
            static InnerClass2()
            {
                Console.WriteLine("InnerClass2Initialized");
            }
        }
    }
    
    public interface IService
    {
        void SayHello();
    }
    
    public partial class ServiceRegistry
    {
        private static List<Func<IService>> _serviceFactories;
    
        private static void RegisterServiceFactory(Func<IService> serviceFactory)
        {
            // This has to be lazily initialized, because the order of static initialization
            //  isn't defined. RegisterServiceFactory could be called before _serviceFactories
            //  is initialized.
            if (_serviceFactories == null)
                _serviceFactories = new List<Func<IService>>();
    
            _serviceFactories.Add(serviceFactory);
        }
    
        public List<IService> Services { get; private set; }
    
        public ServiceRegistry()
        {
            Services = new List<IService>();
    
            foreach (var serviceFactory in _serviceFactories)
            {
                Services.Add(serviceFactory());
            }
        }
    }
    
    
    // In another file (ServiceOne.cs):
    public class ServiceOne : IService
    {
        void IService.SayHello()
        {
            Console.WriteLine("Hello from ServiceOne");
        }
    }
    
    public partial class ServiceRegistry
    {
        // When OutterClass is initialized, this will force InnerClass1 to be initialized.
        private static int _serviceOneRegistryInitializer = ServiceOneRegistry.Initialize;
    
        private static class ServiceOneRegistry
        {
            public static int Initialize = 0;
    
            static ServiceOneRegistry()
            {
                ServiceRegistry.RegisterServiceFactory(() => new ServiceOne());
            }
        }
    }
    
    // In another file (ServiceTwo.cs):
    public class ServiceTwo : IService
    {
        void IService.SayHello()
        {
            Console.WriteLine("Hello from ServiceTwo");
        }
    }
    
    public partial class ServiceRegistry
    {
        // When OutterClass is initialized, this will force InnerClass1 to be initialized.
        private static int _serviceTwoRegistryInitializer = ServiceTwoRegistry.Initialize;
    
        private static class ServiceTwoRegistry
        {
            public static int Initialize = 0;
    
            static ServiceTwoRegistry()
            {
                ServiceRegistry.RegisterServiceFactory(() => new ServiceTwo());
            }
        }
    }
    
    static void Main(string[] args)
    {
        ServiceRegistry registry = new ServiceRegistry();
        foreach (var service in registry.Services)
        {
            serivce.SayHello();
        }
    
        // Output will be:
        // Hello from ServiceOne
        // Hello from ServiceTwo
    
        // No guarantee on order.
    }