一、 构造函数
1. 为什么需要构造函数?
由于难于被检查出来的如正确初始化或清除造成的错误,C#提供了构造函数用于初始化对象,用分析函数清理对象。当对象被创建时,构造函数被自动执行。当对象消亡时,析构函数被自动执行。这样就不用担心忘记对象的初始化和清除工作。
2. 构造函数的调用
a) 只要实例化就会调用构造函数,new。只要实例过一次就不再自动调用构造函数。
b) 重点讨论:当基类指向派生类的实例化。
l 构造函数的层次结构。
l 实例化的对象是child。
l 除了override外所有都是调用root类的方法,这意味着派生类的派生方法等将被忽略。
实例:创建父类root,由其派生child类。实例化root;基类指向派生类的实例化(root=new child());实例化派生类child。三个实例化会发现很有趣的变化。
{ public class Program { public Program() { System.Console.WriteLine("Program的构造函数"); } static void Main(string[] args) { Root root = new Root(); root.Write(); root.Write2(); System.Console.WriteLine("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~`\r\n");
root = new Child(); root.Write(); root.Write2(); System.Console.WriteLine("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~`\r\n");
Child child = new Child(); child.Write(); child.Write2(); System.Console.Read(); } }
public class Root { public Root() { System.Console.WriteLine("Root的构造函数"); } public void Write() { System.Console.WriteLine("Root"); }
public virtual void Write2() { System.Console.WriteLine("Root2 virtual"); }
}
public class Child : Root { public Child() { System.Console.WriteLine("Child的构造函数"); } public new void Write() { System.Console.WriteLine("Child"); }
public override void Write2() { System.Console.WriteLine("Child override Virtual"); //base.Write(); }
public void more() { System.Console.WriteLine("Child override Virtual"); }
} } |
3. 构造函数的分类
a) 静态构造函数
静态构造函数是实现对一个类进行初始化的方法成员。它一般用于对静态数据的初始化。静态构造函数不能有参数,不能有修饰符而且不能被调用,当类被加载时,类的静态构造函数自动被调用。
二、 析构函数和垃圾回收器在C#中的运用
析构函数是实现销毁一个类的实例的方法成员。析构函数不能有参数,不能任何修饰符而且不能被调用。由于析构函数的目的与构造函数的相反,就加前缀‘~’以示区别。
虽然C#(更确切的说是CLR)提供了一种新的内存管理机制---自动内存管理机制(Automatic memory management),资源的释放是可以通过“垃圾回收器” 自动完成的,一般不需要用户干预,但在有些特殊情况下还是需要用到析构函数的,如在C#中非托管资源的释放。
资源的释放一般是通过"垃圾回收器"自动完成的,但具体来说,仍有些需要注意的地方:
1. 值类型和引用类型的引用其实是不需要什么"垃圾回收器"来释放内存的,因为当它们出了作用域后会自动释放所占内存,因为它们都保存在栈(Stack)中;
2. 只有引用类型的引用所指向的对象实例才保存在堆(Heap)中,而堆因为是一个自由存储空间,所以它并没有像"栈"那样有生存期("栈"的元素弹出后就代表生存期结束,也就代表释放了内存),并且要注意的是,"垃圾回收器"只对这块区域起作用;
然而,有些情况下,当需要释放非托管资源时,就必须通过写代码的方式来解决。通常是使用析构函数释放非托管资源,将用户自己编写的释放非托管资源的代码段放在析构函数中即可。需要注意的是,如果一个类中没有使用到非托管资源,那么一定不要定义析构函数,这是因为对象执行了析构函数,那么"垃圾回收器"在释放托管资源之前要先调用析构函数,然后第二次才真正释放托管资源,这样一来,两次删除动作的花销比一次大多的。下面使用一段代码来示析构函数是如何使用的:
三、 静态函数、变量
什么是静态函数:用static修饰的函数。
静态函数和非静态函数最大的区别:静态函数不需要实例化就可以调用、静态函数占用内存比较多,因为一但运行就不会销毁。
注意静态构造函数只能对静态数据成员进行初始化,而不能对非静态数据成员进行初始化。