我试过了,但找不到这两者的区别:
public class MyClass
{
public MyClass(){
MyProperty = "value";
}
public string MyProperty { get; set; }
}
:
public class MyClass
{
public MyClass(){
}
public string MyProperty { get; set; } = "value";
}
任何信息都很好。即使它只是第二个操作的名称
字段初始化式和构造函数之间有一些细微的区别。
首先,它们的顺序:
编译器的目标是以确定的方式构造对象。编译器将始终确保所有的类和实例变量都被完全初始化,然后才能使实例(this
)可供引用。
在类的实例化时,编译器将首先运行所有的类变量(即静态字段)初始化器,因为类变量可以被实例变量初始化器和实例构造函数引用。如果没有定义初始化式,则将变量初始化为其类型的默认值。
类变量和实例变量的初始化都按照声明的顺序进行。
静态字段初始化器运行后,执行类构造函数:
class A
{
private static int StaticField = 2; // #1
// The compiler must ensure that the static field is already initialized.
private int instanceField = A.StaticField; // #3
static A() // #2
{}
}
第二,实例引用(this
)的可用性:
接下来,在类构造函数之后,执行实例变量初始化器(第二个示例)。在构造的这个阶段,编译器还没有创建一个有效的实例。实例(this
)只有在所有实例字段初始化并且构造函数初始化(this()
或base()
)完成后才可用。
因此,仍然没有可用的this
参考。
这意味着实例变量初始化器不能引用其他实例变量. 只允许使用类变量(因为它们已经初始化了)。
在实例变量初始化式之后,执行实例构造函数初始化式,最后执行实例构造函数体:
class A
{
// The compiler ensures that the static field is already initialized.
private int instanceFieldA = A.StaticField; // #3
private static int StaticField = 2; // #1
// The reference of an instance at variable initialization will create a compile-time error
private int instanceFieldB = this.instanceFieldA; // #4
static A() // #2
{}
// The base constructor initializer is executed before the constructor of this.
// Therefore, the instance is still not ready and cannot be referenced at this point.
// As a result, the constructor intializers 'base()' and 'this()' cannot reference instance variables.
public A() : base(this.instanceFIledA) // #5 - Will generate a compile-time error
{
// When the constructor body is executed,
// the instance initializers and constructor initializer are all completed
// and the instance can therefore be referenced.
int value = this.instanceFieldA;
}
}
最重要的是,当您需要基于其他实例变量初始化实例变量时,初始化只允许在实例构造函数中进行。
还因为实例变量初始化器在构造函数初始化器之前执行(例如,base()
),它们的初始值在virtual
成员的情况下将在父类(父类)中可用和有效:
class Superclass
{
virtual string Value { get; } = "From base";
public Superclass()
{
// Will output the value from the subclass' initializer: "From sub"
Debug.WriteLine(this.Value);
}
}
class Subclass : Superclass
{
override string Value { get; } = "From sub";
public Subclass()
{
// Will output the value from this initializer: "From sub"
Debug.WriteLine(this.Value);
}
}
如果在上面的例子中,virtual
属性已经从实例构造函数(您的第一个例子)初始化,
超类将访问一个返回默认值的属性,在这种情况下是null
(因此,超类将抛出):
class Superclass
{
// The initializer is ignored because the property is overridden by the subclass
virtual string Value { get; } = "From base";
public Superclass()
{
// Will throw a 'NullReferenceException' because 'Value' is initialized with the default value of type string (NULL).
Debug.WriteLine(this.Value);
}
}
class Subclass : SuperClass
{
override string Value { get; }
public Subclass()
{
Value = "From sub";
// Will output: "From sub"
Debug.WriteLine(this.Value);
}
}