深入解析C#编程中的事件
using System.Collections;
class A
{
int x, y, count;
public A() {
x = 1; // Variable initializer
y = -1; // Variable initializer
object(); // Invoke object() constructor
count = 0;
}
public A(int n) {
x = 1; // Variable initializer
y = -1; // Variable initializer
object(); // Invoke object() constructor
count = n;
}
}
class B: A
{
double sqrt2;
ArrayList items;
int max;
public B(): this(100) {
B(100); // Invoke B(int) constructor
items.Add("default");
}
public B(int n): base(n - 1) {
sqrt2 = Math.Sqrt(2.0); // Variable initializer
items = new ArrayList(100); // Variable initializer
A(n - 1); // Invoke A(int) constructor
max = n;
}
}
注意变量初始化函数被转换为赋值语句,并且那个赋值语句在对基类构造函数调用前执行。这个顺序确保了所有实例域在任何访问实例的语句执行前,被它们的变量初始化函数初始化。例如:
class A
{
public A() {
PrintFields();
}
public virtual void PrintFields() {}
}
class B: A
{
int x = 1;
int y;
public B() {
y = -1;
}
public override void PrintFields() {
Console.WriteLine("x = {0}, y = {1}", x, y);
}
}
当new B() 被用来创建B的实例时,产生下面的输出:
x = 1, y = 0
因为变量初始化函数在基类构造函数被调用前执行,所以x的数值是1。可是,y的数值是0(int的默认数值),这是因为对y的赋值直到基类构造函数返回才被执行。
默认构造函数
如果一个类不包含任何构造函数声明,就会自动提供一个默认的构造函数。默认的构造函数通常是下面的形式
public C(): base() {}
这里C是类的名称。默认构造函数完全调用直接基类的无参数构造函数。如果直接基类中没有可访问的无参数构造函数,就会发生错误。在例子中
class Message
{
object sender;
string text;
}
因为类不包含构造函数声明,所以提供了一个默认构造函数。因此,这个例子正好等同于
class Message
{
object sender;
string text;
public Message(): base() {}
}
私有构造函数
当一个类只声明了私有的构造函数时,其他类就不能从这个类派生或创建类的实例。私有构造函数通常用在只包含静态成员的类中。例如:
public class Trig
{
private Trig() {} // Prevent instantiation
public const double PI = 3.14159265358979323846;
public static double Sin(double x) {...}
public static double Cos(double x) {...}
public static double Tan(double x) {...}
}
Trig 类提供了一组相关的方法和常数,但没有被例示。因此,它声明了一个单独的私有构造函数。注意至少要必须声明一个私有构造函数来避免自动生成默认的构造函数(它通常有公共的访问性)。
可选的构造函数参数
构造函数的this(...) 形式通常用于与实现可选的构造函数参数的关联上。在这个例子中
class Text
{
public Text(): this(0, 0, null) {}
public Text(int x, int y): this(x, y, null) {}
public Text(int x, int y, string s) {
// Actual constructor implementation
}
}
前两个构造函数只是为丢失的参数提供了默认的数值。两个都使用了一个this(...)构造函数的初始化函数来调用第三个构造函数,它实际上做了对新实例进行初始化的工作。效果是那些可选的构造函数参数:
Text t1 = new Text(); // Same as Text(0, 0, null)
Text t2 = new Text(5, 10); // Same as Text(5, 10, null)
Text t3 = new Text(5, 20, "Hello");
析构函数
析构函数是一个实现破坏一个类的实例的行为的成员。析构函数使用析构函数声明来声明:
一个析构函数声明的标识符必须为声明析构函数的类命名,如果指定了任何其他名称,就会发生一个错误。
析构函数声明的主体指定了为了对类的新实例进行初始化而执行的语句。这于一个有void返回类型的实例方法的主体相关。
例子
class Test
{
static void Main() {
A.F();
B.F();
}
}
class A
{
static A() {
Console.WriteLine("Init A");
}
public static void F() {
Console.WriteLine("A.F");
}
}
class B
{
static B() {
Console.WriteLine("Init B");
}
public static void F() {
Console.WriteLine("B.F");
}
}
会产生或者是下面的输出:
Init A
A.F
Init B
B.F
或者是下面的输出:
Init B
Init A
A.F
B.F

