字段初始化

use*_*348 19 .net c# oop

以下两种字段初始化方式之间是否存在差异?什么时候使用哪一个?

第一种方式

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

存在一个细微的差别,因为第二个示例中的字段将在初始化基类中的字段之前初始化,并且第一个示例中的字段将在之后初始化.然而,这很少有任何影响.

这主要是风格和偏好的问题.我个人更喜欢第二个,因为它使构造函数更加清晰,可以进行更多基于逻辑的初始化,但是有一个强有力的理由可以在构造函数中完成所有初始化.

为了完整起见,初始化顺序如下:

  1. 静态字段
  2. 静态构造函数
  3. 实例字段
  4. 基本静态字段
  5. 基础静态构造函数
  6. 基本实例字段
  7. 基础构造函数
  8. 构造函数

  • @serhio:总是调用基础构造函数,即使你没有明确它.如果没有对基础构造函数进行显式调用,则在派生构造函数的开头调用默认(无参数)构造函数(因此,如果基类不提供公共或受保护的默认构造函数,则会导致编译器错误的原因不要告诉它打电话给谁. (2认同)

Ode*_*ded 6

除了代码行数之外,还有细微差别.

例如,字段初始化在构造函数运行之前发生.在你的例子中没有太大的区别,但要记住.

我会将第二个示例中的字段初始化保留为简单的(字符串或整数),以避免在初始化期间发生可能的异常.

如上所述,在两种方式中,字段都可以只读,因为只能在构造期间写入只读字段.