首页 文章

静态构造函数有什么用?

提问于
浏览
253

请向我解释一下静态构造函数的用法 . 我们为什么以及何时创建静态构造函数,是否可以重载一个?

9 回答

  • -3

    不,你不能超载它;静态构造函数对于初始化与类型(或任何其他每类操作)相关联的任何静态字段非常有用 - 特别适用于将所需的配置数据读入只读字段等 .

    它在第一次运行时由运行时自动运行(确切的规则很复杂(参见"beforefieldinit"),并在CLR2和CLR4之间巧妙地改变) . 除非您滥用反射,否则保证最多运行一次(即使两个线程同时到达) .

  • 11

    来自Static Constructors (C# Programming Guide)

    静态构造函数用于初始化任何静态数据,或执行仅需执行一次的特定操作 . 在创建第一个实例或引用任何静态成员之前自动调用它 . 静态构造函数具有以下属性:静态构造函数不接受访问修饰符或具有参数 . 在创建第一个实例或引用任何静态成员之前,会自动调用静态构造函数来初始化类 . 无法直接调用静态构造函数 . 用户无法控制何时在程序中执行静态构造函数 . 静态构造函数的典型用法是当类使用日志文件并且构造函数用于将条目写入此文件时 . 当构造函数可以调用LoadLibrary方法时,静态构造函数在为非托管代码创建包装类时也很有用 .

  • 4

    当静态字段相互依赖时,静态构造函数也非常有用,这样初始化顺序很重要 . 如果您通过更改字段顺序的格式化程序/美化程序运行代码,那么您可能会发现自己的值为空值,而您并不期望它们 .

    示例:假设我们有这个类:

    class ScopeMonitor
    {
        static string urlFragment = "foo/bar";
        static string firstPart= "http://www.example.com/";
        static string fullUrl= firstPart + urlFragment;
    }
    

    当您访问 fullUr 时,它将是“http://www.example.com/foo/bar” .

    几个月后,你正在清理你的代码并按字母顺序排列字段(假设它们是一个更大的列表的一部分,所以你没有注意到这个问题) . 你有:

    class ScopeMonitor
    {
        static string firstPart= "http://www.example.com/";
        static string fullUrl= firstPart + urlFragment;
        static string urlFragment = "foo/bar";
    }
    

    您的 fullUrl 值现在只是“http://www.example.com/”,因为 urlFragment 在设置 fullUrl 时尚未初始化 . 不好 . 因此,您添加一个静态构造函数来处理初始化:

    class ScopeMonitor
    {
        static string firstPart= "http://www.example.com/";
        static string fullUrl;
        static string urlFragment = "foo/bar";
    
        static ScopeMonitor()
        {
            fullUrl= firstPart + urlFragment;
    
        }
    }
    

    现在,无论您拥有哪些字段,初始化始终都是正确的 .

  • 217

    1.它只能访问类的静态成员 .

    原因:非静态成员特定于对象实例 . 如果允许静态构造函数在非静态成员上工作,它将反映所有对象实例中的更改,这是不切实际的 .

    2.静态构造函数中应该没有参数 .

    原因:因为,它将由CLR调用,没有人可以将参数传递给它 . 3.只允许一个静态构造函数 .

    原因:重载需要两个方法在方法/构造函数定义方面不同,这在静态构造函数中是不可能的 .

    4.它应该没有访问修饰符 .

    原因:原因是同样的调用静态构造函数是由CLR而不是对象,不需要对它进行访问修饰

  • 105

    您可以使用静态构造函数初始化静态字段 . 它在使用这些字段之前的不确定时间运行 . 微软的文档和许多开发人员都警告说,类型上的静态构造函数会产生很大的开销 .
    最好避免使用静态构造函数以获得最佳性能 .
    update: 您不能在同一个类中使用多个静态构造函数,但是您可以将其他实例构造函数与(最多)一个静态构造函数一起使用 .

  • 2

    为什么以及何时创建静态构造函数......?

    使用静态构造函数的一个具体原因是创建'super enum'类 . 这是一个(简单,人为)的例子:

    public class Animals
    {
        private readonly string _description;
        private readonly string _speciesBinomialName;
    
        public string Description { get { return _description; } }
        public string SpeciesBinomialName { get { return _speciesBinomialName; } }
    
        private Animals(string description, string speciesBinomialName)
        {
            _description = description;
            _speciesBinomialName = speciesBinomialName;
        }
    
        private static readonly Animals _dog;
        private static readonly Animals _cat;
        private static readonly Animals _boaConstrictor;
    
        public static Animals Dog { get { return _dog; } }
        public static Animals Cat { get { return _cat; } }
        public static Animals BoaConstrictor { get { return _boaConstrictor; } }
    
        static Animals()
        {
            _dog = new Animals("Man's best friend", "Canis familiaris");
            _cat = new Animals("Small, typically furry, killer", "Felis catus");
            _boaConstrictor = new Animals("Large, heavy-bodied snake", "Boa constrictor");
        }
    }
    

    你可以使用它(在语法外观上)与任何其他枚举非常相似:

    Animals.Dog
    

    这比普通 enum 的优势在于您可以轻松地封装相关信息 . 一个缺点是您不能在 switch 语句中使用这些值(因为它需要常量值) .

  • -1

    Static Constructor

    使用static修饰符声明的构造函数是静态构造函数 . 静态构造函数用于初始化静态数据或执行一个特定的动作,只需要在课程的生命周期中执行一次 . 静态构造函数是在类中执行的第一个代码块 . 静态构造函数在类的生命周期中执行一次且仅执行一次 . 它会自动调用 . 静态构造函数不接受任何参数 . 它没有访问说明符 . 它不是直接调用的 .

  • 7

    静态构造函数用于在第一次引用类时初始化静态数据成员,而实例构造函数用于使用关键字创建该类的实例 .

    资料来源:http://www.c-sharpcorner.com/article/static-constructor-in-C-Sharp-and-their-usages/

  • 85
    using System;
    namespace Constructor
    {
    class Test
    {
    //Declaration and initialization of static data member 
    private static int id = 5;
    public static int Id
    {
    get
    {
    return id;
    }
    }
    public static void print()
    {
    Console.WriteLine("Test.id = " + id);
    }
    static void Main(string[] args)
    {
    //Print the value of id 
    Test.print();
    }
    }
    }
    
    In the above example, static data member <id> is declared and initialized in same line. So if you compile and run this program your output would look similar to this :
    
    Test.id = 5
    
    Lets create one more class similar to class Test but this time the value of its static data member would depend on the value of static data member <id> of class Test.id.
    
    //File Name : Test1.cs
    using System;
    namespace Constructor
    {
    class Test1
    {
    private static int id ;
    //Static constructor, value of data member id is set conditionally here. 
    //This type of initialization is not possible at the time of declaration.
    static Test1()
    {
    if( Test.Id < 10 )
    {
    id = 20;
    }
    else
    {
    id = 100; 
    }
    Console.WriteLine("Static<Class> Constructor for Class Test1 Called..");
    }
    public static void print()
    {
    Console.WriteLine("Test1.id = " + id);
    }
    static void Main(string[] args)
    {
    //Print the value of id 
    Test1.print();
    }
    }
    }
    
    As you can see in the above static constructor, static data member <id> is initialized conditionally. This type of initialization is not possible at the time of declaration. This is where static constructor comes in picture
    

相关问题