总结:CLR Via C#(第八章):构造器
实例构造器和类(引用类型):
1、 类只能拥有类自己的实例构造器;实例构造器不能被继承;
2、 以下修饰符不能用于实例构造器:virtual、new、override、sealed、abstract;
如果类的修饰符为abstract,那么默认构造器可访问性为protected,否则为public;
3、 如果基类没有提供无参构造器,那么类必须显示调用基类的构造器,否则编译出错;
public abstract class Base2
{
public Base2(int i)
{
Console.WriteLine("Base2:" + i);
}
}
//Error:“Base2”方法没有采用“”个参数的重载
//public class Child2 : Base2
//{
//}
public class Child2: Base2
{
public Child2(int i):base(i)
{
Console.WriteLine("Child2:" + i);
}
}
如果类的修饰符为static(sealed、abstract),那么编译器不会在类的定义中生成一个默认的构造器;
4、 类的实例构造器在访问基类继承的任何字段之前,必须调用其基类的构造器;
5、 在构造器中不能调用任何虚方法(虽然编译无错),这样会影响所创建的对象,导致无法预测;
public abstract class Base2
{
public Base2()
{
Virtual_Fn();
}
public virtual void Virtual_Fn()
{
Console.WriteLine("Base2:Virtual_Fn");
}
}
public class Child2 : Base2
{
public Child2()
{
Virtual_Fn();
}
public override void Virtual_Fn()
{
Console.WriteLine("Child2:Virtual_Fn");
}
}
输出:
Child2:Virtual_Fn
Child2:Virtual_Fn
6、 下面的代码中,类有三个构造器,所以编译器产生三次初始化m_x、m_s、m_d——每次构造器一次;
internal sealed class SomeType {
private Int32 m_x = 5;
private String m_s = "Hi there";
private Double m_d = 3.14159;
private Byte m_b;
// Here are some constructors.
public SomeType() { /* ... */ }
public SomeType(Int32 x) { /* ... */ }
public SomeType(String s) { /* ...; */ m_d = 10; }
}
可以将公共初始化语句放到一个单独的初始化构造器中,以减少生成的代码大小;
改造如下:
internal sealed class SomeType
{
// Do not explicitly initialize the fields here
private Int32 m_x;
private String m_s;
private Double m_d;
private Byte m_b;
// This method MUST be called by all constructors.
public SomeType()
{
m_x = 5;
m_s = "Hi there";
m_d = 3.14159;
m_b = 0xff;
}
// This constructor sets all fields to their default, then changes m_x.
public SomeType(Int32 x) : this()
{
m_x = x;
}
// This constructor sets all fields to their default, then changes m_s.
public SomeType(String s) : this()
{
m_s = s;
}
}
实例构造器和结构(值类型):
1、 CLR允许创建值类型的实例,但是无法阻止值类型的初始化,因此值类型实际上不需要在其内部定义构造器;
值类型的构造器只有在被显式调用时才会执行;
C#不允许值类型显式定义无参构造器;
//Error:结构不能包含显式的无参数构造函数
//public struct Point
//{
// public Point()
// {
// }
//}
2、 值类型的构造器必须初始化值类型的所有字段;
public struct Point
{
private int m_x;
private int m_y;
// Error:必须给所有字段初始化
public Point(int x)
{
m_x = x;
// m_y没有被初始化
}
}
类型构造器(静态构造器):
1、 类型构造器可以用于接口、引用类型、值类型;
2、 一般不在类型内部定义类型构造器,如果定义,不能超过一个;
3、 C#自动将类型构造器标记为private,类型构造器前不能有访问修饰符;
public class Base1
{
// Error:静态构造器必须无参
static Base1(int i)
{
}
// Error:类型构造器不允许出现访问修饰符
private static Base1()
{
}
}
4、 永远不要在值类型中定义类型构造器,虽然可以这样做,因为CLR中存在不调用值类型的静态构造器的情况;
internal struct SomeValueType
{
public int m_x;
static SomeValueType()
{
Console.WriteLine("Static 构造器");
}
}
static void Main(string[] args)
{
SomeValueType some = new SomeValueType();
Console.WriteLine(some.m_x);
Console.ReadLine();
}
输出:0
静态构造器没有执行;
5、使用静态构造器时,要注意多线程同步;