9. 构造函数和析构函数
构造函数和析构函数:
编写代码时,如果没有编写他们则编译器会自动添加。
1、构造函数(特殊的方法)
每当创建类或结构时,将会调用其构造函数。类或结构可能具有采用不同参数的多个构造函数。使用构造函数,程序员能够设置默认值、限制实例化,并编写灵活易读的代码。
(1)特点和作用
帮助我们初始化对象,给对象的每个字段依次赋值;
构造函数没有返回值,连 void 也不能写,一般为 public;
构造函数的名称必须跟类名一样;
方法自动运行,无需显示调用;
类中会有一个默认的无参数的构造函数,当你写一个新的构造函数时,那个默认的无参数构造函数就会被覆盖掉。
(2)私有构造函数
私有构造函数是一种特殊的实例构造函数。他通常用于只包含静态成员的类中。如果类具有一个或多个私有构造函数而没有公共构造函数,则其他类(除嵌套类外)无法创建该类的实例。例如:
class NLog { private NLog() { } public static double e = Math.E; //2.71828... }
无参构造函数:
声明空构造函数可阻止自动生成无参构造函数。
私有无参构造函数:请注意,如果不对构造函数使用访问修饰符,则在默认情况下它仍为私有构造函数。但是,通常会显式地使用 private 修饰符来清楚地表明该类不能被实例化。(如 继承于 Unity 的 MonoBehaviour 的类使用无参构造函数可防止该类被实例化。)
(3)静态构造函数
静态构造函数用于初始化任何静态数据,或执行仅需执行一次的特定操作。将在创建第一个实例或引用任何静态成员之前自动调用静态构造函数。
class SimpleClass { // Static variable that must be initialized at run time. static readonly long baseline; // Static constructor is called at most one time, before any // instance constructor is invoked or member is accessed. static SimpleClass() { baseline = DateTime.Now.Ticks; } }
3、静态构造函数具有以下属性:
静态构造函数不使用访问修饰符或不具有参数。
类或结构只能有一个静态构造函数。
静态构造函数不能继承或重载。
静态构造函数不能直接调用,并且仅应由公共语言运行时 (CLR) 调用。 可以自动调用它们。
用户无法控制在程序中执行静态构造函数的时间。
在创建第一个实例或引用任何静态成员之前,将自动调用静态构造函数以初始化类。 静态构造函数应在实例构造函数之前运行。 调用(而不是分配)分配给事件或委托的静态方法时,将调用类型的静态构造函数。 如果静态构造函数类中存在静态字段变量初始值设定项,它们将在执行静态构造函数之前立即以在类声明中显示的文本顺序执行。
如果未提供静态构造函数来初始化静态字段,会将所有静态字段初始化为其默认值,如 C# 类型的默认值中所列。
如果静态构造函数引发异常,运行时将不会再次调用该函数,并且类型在程序运行所在的应用程序域的生存期内将保持未初始化。 大多数情况下,当静态构造函数无法实例化一个类型时,或者当静态构造函数中发生未经处理的异常时,将引发 TypeInitializationException 异常。 对于未在源代码中显式定义的隐式静态构造函数,故障排除可能需要检查中间语言 (IL) 代码。
静态构造函数的存在将防止添加 BeforeFieldInit 类型属性。 这将限制运行时优化。
声明为 static readonly 的字段可能仅被分配为其声明的一部分或在静态构造函数中。 如果不需要显式静态构造函数,请在声明时初始化静态字段,而不是通过静态构造函数实现更好的运行时优化。
用法
静态构造函数的一种典型用法是在类使用日志文件且将构造函数用于将条目写入到此文件中时使用。
静态构造函数对于创建非托管代码的包装类也非常有用,这种情况下构造函数可调用 LoadLibrary 方法。
也可在静态构造函数中轻松地对无法在编译时通过约束(类型参数约束)检查的类型参数强制执行运行时检查。
2、析构函数
(1)是实现销毁一个类的实例方法成员;
(2)他不能有参数,也不能有任何修饰符而且不能被调用 ;
(3)析构函数前加缀 “~” ;
(4)编写一些关于本类对象消失(清除)前的一些必要处理工作;
(5)常用于数据库,数据连接的关闭,或者 Socket 数据连接的关闭 。
例:
1 namespace ProgramTest 2 { 3 //主类 4 class Program 5 { 6 static void Main(string[] args) 7 { 8 //利用构造函数及调用方法输出 9 Clerk zsClerk = new Clerk("张三", Gender.女, 100); 10 zsClerk.Wrte(); 11 Console.ReadKey(); 12 } 13 } 14 15 /// <summary> 16 /// 新建类Clerk,声明变量(字段)、生成属性及利用构造函数初始化字段 17 /// </summary> 18 /// 枚举 19 public enum Gender 20 { 21 男, 22 女 23 } 24 class Clerk 25 { 26 //声明变量及添加属性 27 private string _name; //声明变量 28 public string Name //添加属性。生成属性快捷键:Ctrl + r +e 29 { 30 get 31 { 32 return _name; 33 } 34 35 set 36 { 37 _name = value; 38 } 39 } 40 private Gender _gender; //声明变量 41 public Gender Gender //添加属性 42 { 43 get 44 { 45 return _gender; 46 } 47 48 set 49 { 50 _gender = value; 51 } 52 } 53 private int _age; //声明变量 54 public int Age //添加属性 55 { 56 get 57 { 58 return _age; 59 } 60 61 set 62 { 63 _age = value; 64 } 65 } 66 67 //创建一个方法 68 public void Wrte() 69 { 70 Console.WriteLine("我叫{0},我是{1}生,我{2}岁了!", this.Name, this.Gender, this.Age); 71 } 72 73 //带参构造函数,对字段进行赋值 74 public Clerk(string name, Gender gender, int age) 75 { 76 this.Name = name; 77 this.Gender = gender; 78 this.Age = age; 79 } 80 81 //创建析构函数 82 ~Clerk() 83 { 84 Console.WriteLine("这是一个析构函数"); 85 } 86 } 87 }