构造函数(C# 编程指南)
- 构造函数概述
- 使用构造函数
- 构造函数分类
- 实例构造函数
- 私有构造函数
- 静态构造函数
构造函数概述
每当创建类或结构时,将会调用其构造函数。 类或结构可能具有采用不同参数的多个构造函数。 使用构造函数,程序员能够设置默认值、限制实例化,并编写灵活易读的代码。 有关详细信息和示例,请参阅使用构造函数和实例构造函数。
构造函数语法
构造函数是一种方法,其名称与其类型的名称相同。 其方法签名仅包含方法名称和其参数列表;它不包含返回类型。 以下示例演示一个名为 Person
的类的构造函数。
构造函数分类
构造函数可分为:实例构造函数,静态构造函数,私有构造函数
实例构造函数分为:有参数构造函数、无参构造函数
实例构造函数
无参数构造函数
如果没有为类提供构造函数,则 C# 将默认创建一个构造函数,该函数会实例化对象并将成员变量设置为默认值,如 C# 类型的默认值中所列。 如果没有为结构提供构造函数,C# 将依赖于隐式无参数构造函数,自动将每个字段初始化为其默认值。 有关详细信息和示例,请参阅实例构造函数
下面的示例说明包含两个类构造函数的类:一个不带参数,另一个带有两个参数 初始化类。
class Coords { public int x, y; // Parameterless constructor. public Coords() { x = 0; y = 0; } // A constructor with two parameters. public Coords(int x, int y) { this.x = x; this.y = y; } public override string ToString() { return $"({x},{y})"; } } class MainClass { static void Main() { var p1 = new Coords(); var p2 = new Coords(5, 3); Console.WriteLine($"Coords #1 at {p1}"); Console.WriteLine($"Coords #2 at {p2}"); Console.ReadKey(); } } /* Output: Coords #1 at (0,0) Coords #2 at (5,3) */
私有构造函数
类成员有private修饰符,就不允许在类范围以外访问这个类成员。对类构造函数应用private修饰符时,则禁止外部类创建该类的实例。
类是通过无参构造函数实例化的。对类构造函数应用private修饰符时,防止从外部实例化类。既然不能实例化,那么这个类还有什么用处?但实际上这是一个功能极其强大的特性。
虽然私有构造函数不允许外部方法实例化这个类,但却允许此类中的公共方法(有时也称为工厂方法,factory method)创建对象。也就是说,类可以创建自身的实例、控制外界对它的访问,以及控制创建的实例个数
静态构造函数
类的静态构造函数用于 初始化任何类本身的静态数据 ,所以不允许有访问修饰符,静态构造函数是无参构造函数,一个类只有一个静态构造函数,或执行仅需执行一次的特定操作。 将在创建第一个实例或引用任何静态成员之前自动调用静态构造函数。
我们在调用类的静态字段的时候,类会调用静态无参构造函数来初始化。静态构造函数不是必须的。
类的初始化过程: 初始值设定项>静态构造函数>实例构造函数
静态构造函数具有以下属性:
-
静态构造函数不使用访问修饰符或不具有参数。
-
类或结构只能有一个静态构造函数。
-
静态构造函数不能继承或重载。
-
静态构造函数不能直接调用,并且仅应由公共语言运行时 (CLR) 调用。 可以自动调用它们。
-
用户无法控制在程序中执行静态构造函数的时间。
-
自动调用静态构造函数。 将在创建第一个实例或引用任何静态成员之前初始化类。 静态构造函数在实例构造函数之前运行。 调用(而不是分配)分配给事件或委托的静态方法时,将调用类型的静态构造函数。 如果静态构造函数类中存在静态字段变量初始值设定项,它们将以在类声明中显示的文本顺序执行。 初始值设定项紧接着执行静态构造函数之前运行。
-
如果未提供静态构造函数来初始化静态字段,会将所有静态字段初始化为其默认值,如 C# 类型的默认值中所列。
-
如果静态构造函数引发异常,运行时将不会再次调用该函数,并且类型在应用程序域的生存期内将保持未初始化。 大多数情况下,当静态构造函数无法实例化一个类型时,或者当静态构造函数中发生未经处理的异常时,将引发 TypeInitializationException 异常。 对于未在源代码中显式定义的静态构造函数,故障排除可能需要检查中间语言 (IL) 代码。
-
静态构造函数的存在将防止添加 BeforeFieldInit 类型属性。 这将限制运行时优化。
-
声明为
static readonly
的字段可能仅被分配为其声明的一部分或在静态构造函数中。 如果不需要显式静态构造函数,请在声明时初始化静态字段,而不是通过静态构造函数,以实现更好的运行时优化。 -
运行时在单个应用程序域中多次调用静态构造函数。 该调用是基于特定类型的类在锁定区域中进行的。 静态构造函数的主体中不需要其他锁定机制。 若要避免死锁的风险,请勿阻止静态构造函数和初始值设定项中的当前线程。 例如,不要等待任务、线程、等待句柄或事件,不要获取锁定,也不要执行阻止并行操作,如并行循环、
Parallel.Invoke
和并行 LINQ 查询