版权声明:转载请注明出处 https://blog.csdn.net/le_17_4_6/article/details/86607349
实例构造函数
[构造函数修饰符] 标识符([参数列表] )
[ : base ( [参数列表] ) ] [ : this ( [参数列表] ) ]
{
构造函数语句块
}
- 构造函数修饰符有public、protected、internal、private
- 构造函数可以重载
- :base表示调用直接基类中的实例构造函数
- :this调用该类本身所声明的其他构造函数
- 构造函数语句块既可以对静态字段赋值,也可以对非静态字段进行初始化
- 实例构造函数不能被继承
- 如果一个类中没有声明任何实例构造函数,则系统会提供一个默认的实例构造函数
- 一旦类中提供了自定义的构造函数,系统则不提供默认构造函数
- 如果变量是方法的局部变量或者是方法的out参数,编译器就会认为在使用该变量前,代码必须给它显式地设置一个值
- 对于其他情况(包括类的实例和静态成员字段),编译器会在创建变量时,把变量初始化为默认值
- 当创建派生类对象时
- 调用成员对象的构造函数
- 调用基类构造函数
- 执行派生类的构造函数
- 默认情况下执行基类的无参构造函数
- 如果要执行基类的有参构造函数,则必须在派生类构造函数的基类列表中指出
字段初始化
using System;
using System.Collections.Generic;
using System.Text;
namespace FieldInitialize
{
public class A
{
private static int InitX()
{
Console.WriteLine("A.InitX()");
return 1;
}
private static int InitY()
{
Console.WriteLine("A.InitY()");
return 2;
}
private static int InitA()
{
Console.WriteLine("A.InitA()");
return 3;
}
private static int InitB()
{
Console.WriteLine("A.InitB()");
return 4;
}
private int y = InitY();
private int x = InitX();
private static int a = InitA();
private static int b = InitB();
}
class Program
{
static void Main(string[] args)
{
A a = new A();
Console.ReadLine();
}
}
}
先初始化字段,再调用父类构造函数
using System;
namespace ConstructorExp
{
class Base
{
public Base(int x)
{
Console.WriteLine("Base.Base(int)");//4
this.x = x;
}
private static int InitX()
{
Console.WriteLine("Base.InitX()"); //3
return 1;
}
public int x = InitX();
}
class Derived : Base
{
public Derived(int a)
: base(a)
{
Console.WriteLine("Derived.Derived(int)"); //5
this.a = a;
}
public Derived(int a, int b)
: this(a)
{
Console.WriteLine("Derived.Derived(int,int)"); //6
this.b = b;
}
private static int InitA()
{
Console.WriteLine("Derived.InitA()");//1
return 3;
}
private static int InitB()
{
Console.WriteLine("Derived.InitB()");//2
return 4;
}
public int a = InitA();
public int b = InitB();
}
class Program
{
static void Main(string[] args)
{
Derived b = new Derived(1, 2);
Console.ReadLine();
}
}
}
静态构造函数
- 静态构造函数修饰符:static
- 静态构造函数仅对静态数据成员进行初始化,不能对非静态数据成员进行初始化
- 静态构造函数都是私有的
- 静态构造函数是不可继承的,而且不能被直接调用
- 如果类中没有声明静态构造函数,而又包含带有初始设定的静态字段,那么编译器会自动生成一个默认的静态构造函数
using System;
class A
{
protected static int x;
protected int y;
static A()
{
x = 10; //1
}
public A(int a,int b) //3
{
x = a;
y = b;
}
public void print()
{
Console.WriteLine("x={0},y={1}", x, y);
}
}
class B : A
{
protected new static int x;
private int z;
public B(int a,int b,int c):base(a,b)
{
z = c; //4
}
static B()
{
x = 20; //2
}
new public void print()
{
Console.WriteLine("x={0},y={1},z={2}", x, y, z);
}
}
class Test
{
static void Main()
{
A objA = new B(3, 4, 5);
objA.print();
B objB = (B)objA;
objB.print();
}
}
析构函数
- 析构函数不能被重载,不能被继承
- 一个类如果没有显式声明析构函数,则编译器将自动产生一个默认的析构函数
- 析构函数不能由程序显式调用,由系统在释放对象时调用
- 析构函数是在“垃圾回收器”回收对象的存储空间之前调用的,最终会调用System.Object的Finalize( )
- 可使用System.GC.Collect()请求运行垃圾回收器,例如代 码中有大量的对象刚刚停止使用
- 析构函数在C#中充当鸡肋的角色,由于有垃圾 收集器清理资源,所以不能预计它们会在什么时候运行
- Finalize方法调用时刻是不确定的
- 如果对对象执行了finalize()方法,在对该对象进行无用单元收集时,会对性能产生重大影响。
所以在一般情况下,最好不要执行该方法 - 常见场合是在对象维护不由.NET管理的资源时,例如文件或数据库连接,需要执行finalize断开这些连接
- Dispose()和Close()方法优点是资源在不需要时立即被释放,对于像独占文件锁那样的对象来说是非常好的
- Close( )主要用于指定资源可能以后会再次打 开,而Dispose( )是一种最终处理,调用Dispose( )意味着客户机代码最终会删除这个对象
- 如关闭一个文件或数据库连接使用Close()释放各种GDI或其他Windows对象的句柄使用 Dispose()
- IDisposable C#提供using语法确保在引用出作用域时,在 对象上自动调用Dispose( )
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
namespace DestructorExp1
{
public class Article : System.IDisposable
{
public int m_Price;
public Article(int price) { this.m_Price = price; }
public void Dispose()
{
Console.WriteLine("m_Price=" + m_Price);
}
}
class Program
{
static void Main(string[] args)
{
Article a = new Article(300);
Article b = new Article(400);
using (a) using(b)
{
}
Console.ReadLine();
}
}
}
必须实现IDisposable接口,才能使用using语法
Class ResourceGobbler: IDisposable
{
……
public void Dispose( )
{
……
}
}
什么情况下需要自己写析构函数?
使用析构函数主要是为了释放资源。
- 如:当该类中打开了一个文件,对象销毁时,应当关闭这个文件。
- 又如:当该类中打开了数据库,对象销毁时,应当关闭这个连接。
- 再如:当该类中申请了大量内存,对象销毁时,应当释放这些内存。
调用析构函数的时机由.NET的垃圾回收器来决定