在构造函数中设置属性值与直接分配给属性

发布于 2025-02-11 11:42:16 字数 429 浏览 2 评论 0原文

我尝试过,但找不到这之间的区别:

public class MyClass
{
    public MyClass(){
        MyProperty = "value";
    }

    public string MyProperty { get; set; }
}

以及:

public class MyClass
{
    public MyClass(){
    }

    public string MyProperty { get; set; } = "value";
}

任何信息都很棒。即使只是第二操作的名称。

I tried but could not find the difference between this:

public class MyClass
{
    public MyClass(){
        MyProperty = "value";
    }

    public string MyProperty { get; set; }
}

and this:

public class MyClass
{
    public MyClass(){
    }

    public string MyProperty { get; set; } = "value";
}

Any information would be great. Even if it's just the name of the second operation.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

半窗疏影 2025-02-18 11:42:16

字段初始化器和构造函数之间存在一些细微的差异。

首先,他们的顺序:
编译器的目的是以确定性的方式构建对象。编译器将始终确保所有类和实例变量在将实例( 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 ):

接下来,在类构造函数之后,执行实例变量初始化器(您的第二个示例) )。在构建阶段,编译器尚未创建有效的实例。实例(此)只有在所有实例字段初始化并构造函数initializer(this()或 base> base())之后才能使用。 。
因此,仍然没有参考可用。

这意味着,实例变量初始化程序不能引用其他实例变量。仅允许类变量(因为它们已经初始化)。

实例变量初始化器后,执行实例构造函数Intializer,然后最后一个实例构造函数正文:

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() (父类):

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); 
  }
}

There are some subtle differences between field initializers and constructors.

First, their order:
The goal of the compiler is to construct an object in a deterministic manner. The compiler will always ensure that all class and instance variables are completely initialized before it will make the instance (this) available for reference.

On instantiation of a class, the compiler will first run all class variable (aka static field) initializers, as class variables can be referenced by both instance variable initializers and instance constructors. If there is no initializer defined, the variable is initialized to the default value of its type.
Initialization of both, class and instance variables, takes place in the order of declaration.

After the static field initializers are run, the class constructor is executed:

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
  {}
}

Second, the availability of the instance reference (this):

Next, after the class constructor, the instance variable initializers are executed (your second example). At this stage of construction, the compiler has not created a valid instance yet. The instance (this) is only available after all instance fields are initialized and the constructor initializer (this() or base()) has completed.
Therefore, there is still no this reference available.

This means, an instance variable initializer cannot reference other instance variables. Only class variables are allowed (because they were already initialized).

After the instance variable initializers, the instance constructor intializer is executed and then finally the instance constructor body:

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;
  }
}

The bottom line, when you need to initialize instance variables based on other instance variable, the initialization is only allowed to take place in the instance constructor.

Also because the instance variable initializers are executed before the constructor initializer (e.g., base()), their initial values in case of virtual members will be available and valid in the superclass (parent class):

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); 
  }
}

If in the above example the virtual property had been initialized from the instance constructor (your first example),
the superclass would access a property that would return the default value, which is null in this case (therefore, the superclass would throw):

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); 
  }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文