当类或结构创建时,其构造函数调用,它们通常用于初始化新对象的数据成员。
一、默认构造函数
在下面的示例中,使用一个简单的构造函数定义了名为 Test的类。 然后使用 new 运算符来实例化该类。 在为新对象分配内存之后,new 运算符立即调用Test 构造函数。
class Test { public int x, y; public Test() { x =1; y = 2; } } class MainClass { static void Main() { Test p1 = new Test(); Console.WriteLine("Test #1 at {0},{1}", p1.x,p1.y); Console.ReadKey(); } } /* Output:Test #1 at 1,2 */
不带参数的构造函数称为“默认构造函数”。无论何时,只要使用new运算符实例化对象,并且不为new提供任何参数,就会调用默认构造函数。
如果某个类没有构造函数,则会自动生成一个默认构造函数,并使用默认值来初始化对象字段。例如,int初始化为 0。有关默认值的更多信息,请参见默认值表(C# 参考)。
二、带参数的构造函数
然而,提供其他构造函数通常十分有用。例如,可以向 CoOrds 类添加构造函数,以便可以为数据成员指定初始值:
class CoOrds { public int x, y; // Default constructor: public CoOrds() { x = 0; y = 0; } // tcA constructor with two arguments: public CoOrds(int x, int y) { this.x = x; this.y = y; } // Override the ToString method: public override string ToString() { return (String.Format("({0},{1})", x, y)); } } class MainClass { static void Main() { CoOrds p1 = new CoOrds(); CoOrds p2 = new CoOrds(5, 3); // Display the results using the overriden ToString method: Console.WriteLine("CoOrds #1 at {0}", p1); Console.WriteLine("CoOrds #2 at {0}", p2); Console.ReadKey(); } } /* Output: CoOrds #1 at (0,0) CoOrds #2 at (5,3) */
三、私有构造函数
通过将构造函数设置为私有构造函数,可以阻止类被实例化,如下所示:
class NLog { // Private Constructor: private NLog() { } public static double e = Math.E; //2.71828... }
声明空构造函数可阻止自动生成默认构造函数。
注意:如果您不对构造函数使用访问修饰符,则在默认情况下它仍为私有构造函数。 但是,通常显式地使用private 修饰符来清楚地表明该类不能被实例化。
四、静态构造函数
静态构造函数用于初始化任何 静态 数据,或用于执行仅需执行一次的特定操作。 在创建第一个实例或引用任何静态成员之前,将自动调用静态构造函数。
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; } }
- 静态构造函数既没有访问修饰符,也没有参数。
- 在创建第一个实例或引用任何静态成员之前,将自动调用静态构造函数来初始化类。
- 无法直接调用静态构造函数。
- 在程序中,用户无法控制何时执行静态构造函数。
- 静态构造函数的典型用途是:当类使用日志文件时,将使用这种构造函数向日志文件中写入项。
- 静态构造函数在为非托管代码创建包装类时也很有用,此时该构造函数可以调用 LoadLibrary 方法。
- 如果静态构造函数引发异常,运行时将不会再次调用该构造函数,并且在程序运行所在的应用程序域的生存期内,类型将保持未初始化。
在派生类中调用基类构造函数:
1. 当基类中没有自己编写构造函数时,派生类默认调用基类的默认构造函数(默认构造函数是指在没有编写构造函数的情况下系统默认的无参构造函数。)
2. 当基类中有自己编写的构造函数时,要在基类中添加无参的构造函数(派生类没有指定调用构造哪个构造函数时,会寻找无参的构造函数,如果么没有无参构造函数会报错)
3. 基类中编写了构造函数,则派生类中可以使用base关键字,指定调用基类的某个构造函数。
下例通过base,指定调用一个参数的构造函数:
public class MyBaseClass { public MyBaseClass(int i) { Console.WriteLine("我是基类带一个参数的构造函数"); } } public class MyDerivedClass : MyBaseClass { /* public MyDerivedClass() : base(i) { Console.WriteLine("我是子类无参构造函数"); } */ //错误 public MyDerivedClass(int i) : base(i) { Console.WriteLine("我是子类带一个参数的构造函数"); } public MyDerivedClass(int i, int j) : base(i) { Console.WriteLine("我是子类带二个参数的构造函数"); } //注意:base(i) 传入的是一个参数,调用的依然是基类中一个参数的构造函数 }
C#父类有一个两个参数的构造函数,其派生类新增了两个属性,现在想在派生类的构造函数中用前两个属性构造基类,用后两个属性构造其自身:
public class A { int i, j; public A(int a, int b) { i = a; j = b; } public override string ToString() { return "i=" + i + ",j=" + j + ""; } } public class B : A { int d, c; public B(int x, int y, int z, int e) : base(x, y) { d = z; c = e; } public new string ToString() { return "d=" + d + ",c=" + c + ""; } } //调用B B b = new B(1, 2, 3, 4); Console.WriteLine(b.ToString()); Console.ReadLine(); A a = b; Console.WriteLine(a.ToString()); Console.ReadLine();
在C#中,派生类不是继承基类的构造函数,只能调用基类的构造函数。 如果不进行调用 则默认调用基类无参构造函数。