以下两种字段初始化方式之间是否存在差异?什么时候使用哪一个?
public class Class1
{
private SomeClass someclass;
public Class1()
{
someclass = new SomeClass(some arg);
}
}
Run Code Online (Sandbox Code Playgroud)
public class Class1
{
private SomeClass someclass = new SomeClass(some arg);
}
Run Code Online (Sandbox Code Playgroud)
第二个例子中的字段可以是只读的.
Ror*_*ory 37
this在初始化内联字段时,您无法使用关键字.这样做的原因是代码的执行顺序:对于所有意图和目的,初始化字段内联的代码在类的构造函数之前运行(即C#编译器将阻止对this关键字的访问).基本上这意味着这将无法编译:
public class Class1
{
private SomeClass someclass = new SomeClass(this);
public Class1()
{
}
}
Run Code Online (Sandbox Code Playgroud)
但这会:
public class Class1
{
private SomeClass someclass;
public Class1()
{
someclass = new SomeClass(this);
}
}
Run Code Online (Sandbox Code Playgroud)
这是一个微妙的差异,但值得记下.
在使用继承时,两个版本之间的其他差异才非常明显.如果你有两个相互继承的类,那么首先初始化派生类中的字段,然后初始化基类中的字段,然后调用基类的构造函数,最后是构造函数.将调用派生类.在某些情况下你需要非常小心,因为如果你没有意识到发生了什么,它可能导致水果沙拉的复杂性(其中一个涉及在基类构造函数中调用虚方法,但是几乎从来都不是一个明智的举动).下面是一个例子:
class BaseClass
{
private readonly object objectA = new object(); // Second
private readonly object objectB;
public BaseClass()
{
this.objectB = new object(); // Third
}
}
class DerivedClass : BaseClass
{
private object objectC = new object(); // First
private object objectD;
public DerivedClass()
{
this.objectD = new object(); // Forth
}
}
Run Code Online (Sandbox Code Playgroud)
您需要在初始化字段的所有行上设置断点,以便能够查看正确的序列.
ICR*_*ICR 35
存在一个细微的差别,因为第二个示例中的字段将在初始化基类中的字段之前初始化,并且第一个示例中的字段将在之后初始化.然而,这很少有任何影响.
这主要是风格和偏好的问题.我个人更喜欢第二个,因为它使构造函数更加清晰,可以进行更多基于逻辑的初始化,但是有一个强有力的理由可以在构造函数中完成所有初始化.
为了完整起见,初始化顺序如下:
除了代码行数之外,还有细微差别.
例如,字段初始化在构造函数运行之前发生.在你的例子中没有太大的区别,但要记住.
我会将第二个示例中的字段初始化保留为简单的(字符串或整数),以避免在初始化期间发生可能的异常.
如上所述,在两种方式中,字段都可以只读,因为只能在构造期间写入只读字段.