C# 静态构造函数与实例构造函数的区别是什么?

187 阅读3分钟

调用时机

  • 静态构造函数

    • 静态构造函数在类被加载到内存时自动执行,且仅执行一次。具体来说,当第一次访问类的静态成员(如静态字段、静态方法或嵌套类型)或者创建类的第一个实例(如果类包含实例成员)时,.NET 运行时会加载该类并执行静态构造函数。例如:
class MyStaticClass
{
    public static int StaticValue;
    static MyStaticClass()
    {
        StaticValue = 10;
    }
}
class Program
{
    static void Main()
    {
        // 当访问StaticValue时,MyStaticClass的静态构造函数会执行
        Console.WriteLine(MyStaticClass.StaticValue);
    }
}

实例构造函数

  • 实例构造函数是在创建类的对象时执行。每次使用new关键字创建一个新的对象实例,都会调用相应的实例构造函数。例如:
class MyInstanceClass
{
    public int InstanceValue;
    public MyInstanceClass()
    {
        InstanceValue = 20;
    }
}
class Program
{
    static void Main()
    {
        // 第一次创建对象时,调用实例构造函数
        MyInstanceClass obj1 = new MyInstanceClass();
        Console.WriteLine(obj1.InstanceValue);
        // 第二次创建对象时,再次调用实例构造函数
        MyInstanceClass obj2 = new MyInstanceClass();
        Console.WriteLine(obj2.InstanceValue);
    }
}

作用对象

静态构造函数

  • 主要用于初始化类的静态成员。这些静态成员在整个类的范围内是共享的,被所有类的实例所共用。例如,一个用于数据库连接的类,其静态构造函数可以初始化一个静态的数据库连接字符串,这个连接字符串在整个应用程序中可以被所有该类的实例使用。

实例构造函数

  • 用于初始化类的实例成员。每个对象实例都有自己独立的实例成员,实例构造函数确保这些成员在对象创建时被正确初始化。例如,一个表示人的类,实例构造函数可以初始化每个人的姓名、年龄等实例属性。

访问修饰符和参数使用情况

静态构造函数

  • 没有访问修饰符(既不能是publicprivateprotected,也不能是internal),且不能有参数。它是由.NET 运行时自动调用的,不需要(也不允许)通过访问修饰符来控制访问权限,也不会接收外部传递的参数。

实例构造函数

  • 可以有访问修饰符,用于控制在何处可以创建类的对象。常见的访问修饰符有public(允许在任何地方创建对象)、private(只能在类内部创建对象)等。同时,实例构造函数可以有参数,通过参数可以在创建对象时传递初始值,用于初始化实例成员。例如:
class MyClassWithParams
{
    public int Value;
    public MyClassWithParams(int value)
    {
        Value = value;
    }
}
class Program
{
    static void Main()
    {
        MyClassWithParams obj = new MyClassWithParams(30);
        Console.WriteLine(obj.Value);
    }
}

继承关系中的行为

  • 静态构造函数

    • 静态构造函数不能被继承。子类不会继承父类的静态构造函数。当子类被加载时,如果它有自己的静态构造函数,那么它自己的静态构造函数会被执行,而与父类的静态构造函数无关;如果子类没有静态构造函数,那么只有父类的静态构造函数(如果有)在父类被加载时执行。
  • 实例构造函数

    • 子类可以继承父类的实例构造函数。如果子类没有定义自己的实例构造函数,它会默认调用父类的无参数实例构造函数(如果有)。如果子类定义了自己的实例构造函数,它可以通过base关键字显式地调用父类的实例构造函数,用于初始化从父类继承的成员。例如:
class Parent
{
    public Parent()
    {
        Console.WriteLine("父类实例构造函数");
    }
}
class Child : Parent
{
    public Child()
    {
        // 调用父类的实例构造函数
        base();
        Console.WriteLine("子类实例构造函数");
    }
}
class Program
{
    static void Main()
    {
        Child c = new Child();
    }
}