C# 构造函数如何将值赋值给只读 属性?
How can C# constructor assign value to read only property?
我写了一个只有 get 访问器的 class 属性,比如:
public int MyProp { get; }
我无法通过我的 class 中的方法为 MyProp 分配任何值,即使是私下也不行,也就是说,如果我有一个私有集,那是不一样的。
但是,不知何故,我可以使用如下构造函数为 myProp 设置一个值:
public MyClass (int myProp) { this.MyProp = myProp; }
构造函数是否总是不受 属性 访问器规范的影响?它们只有在构造函数运行后才有效吗?
当您创建一个 auto-属性 时,编译器会自动生成支持字段来支持它。在只读的情况下(仅get
)属性,情况仍然如此。能够在构造函数中分配给 get
-only 属性 只是编译器支持的 语法糖 。当您分配给 属性 时,编译器会翻译代码,以便它分配给 支持字段 。
例如,假设您的构造函数:
public MyClass(int myProp)
{
this.MyProp = myProp;
}
编译器将其翻译成类似于以下内容的内容:
public MyClass(int myProp)
{
this._myPropBackingField = myProp;
}
您没有 set
访问器的事实会阻止您在其他任何地方分配给 属性。
实际上,支持字段收到一个“无法说出”的名称,该名称是非法的 c#(但有效的 IL),从而阻止 you 尝试直接使用该字段。编译器完成工作后,您的示例实际上如下所示:
public class MyClass
{
[CompilerGenerated]
private readonly int <MyProp>k__BackingField;
public int MyProp
{
[CompilerGenerated]
get
{
return this.<MyProp>k__BackingField;
}
}
public MyClass(int myProp)
{
this.<MyProp>k__BackingField = myProp;
}
}
请注意,构造函数实际上是直接而不是通过属性的set
之三间接分配给支持字段<MyProp>k__BackingField
(毕竟一个都不存在)。
看到这个SharpLab example。
试想如果不允许构造函数初始化这些值,那么这些值有什么用呢?它将始终是数据类型的默认值,就像 int 一样,它将是 0。仅使用 get 意味着我们将不允许在初始化后更改该值。
您也可以使用 readonly,默认情况下它是线程安全的。但是当您使用私有集时,您必须显式处理线程安全。
我写了一个只有 get 访问器的 class 属性,比如:
public int MyProp { get; }
我无法通过我的 class 中的方法为 MyProp 分配任何值,即使是私下也不行,也就是说,如果我有一个私有集,那是不一样的。 但是,不知何故,我可以使用如下构造函数为 myProp 设置一个值:
public MyClass (int myProp) { this.MyProp = myProp; }
构造函数是否总是不受 属性 访问器规范的影响?它们只有在构造函数运行后才有效吗?
当您创建一个 auto-属性 时,编译器会自动生成支持字段来支持它。在只读的情况下(仅get
)属性,情况仍然如此。能够在构造函数中分配给 get
-only 属性 只是编译器支持的 语法糖 。当您分配给 属性 时,编译器会翻译代码,以便它分配给 支持字段 。
例如,假设您的构造函数:
public MyClass(int myProp)
{
this.MyProp = myProp;
}
编译器将其翻译成类似于以下内容的内容:
public MyClass(int myProp)
{
this._myPropBackingField = myProp;
}
您没有 set
访问器的事实会阻止您在其他任何地方分配给 属性。
实际上,支持字段收到一个“无法说出”的名称,该名称是非法的 c#(但有效的 IL),从而阻止 you 尝试直接使用该字段。编译器完成工作后,您的示例实际上如下所示:
public class MyClass
{
[CompilerGenerated]
private readonly int <MyProp>k__BackingField;
public int MyProp
{
[CompilerGenerated]
get
{
return this.<MyProp>k__BackingField;
}
}
public MyClass(int myProp)
{
this.<MyProp>k__BackingField = myProp;
}
}
请注意,构造函数实际上是直接而不是通过属性的set
之三间接分配给支持字段<MyProp>k__BackingField
(毕竟一个都不存在)。
看到这个SharpLab example。
试想如果不允许构造函数初始化这些值,那么这些值有什么用呢?它将始终是数据类型的默认值,就像 int 一样,它将是 0。仅使用 get 意味着我们将不允许在初始化后更改该值。
您也可以使用 readonly,默认情况下它是线程安全的。但是当您使用私有集时,您必须显式处理线程安全。