简体   繁体   English

C# 构造函数如何为只读属性赋值?

[英]How can C# constructor assign value to read only property?

I wrote a class property with only get accessor, like:我写了一个只有 get 访问器的 class 属性,例如:

public int MyProp { get; }

I cannot assign any value to MyProp, not even privately, via method inside my class, ie it's not like if I had a private set.我不能通过我的 class 中的方法为 MyProp 分配任何值,甚至不能私下分配,也就是说,这不像我有一个私有集。 However, somehow, I can set a value to myProp using a constructor like:但是,不知何故,我可以使用如下构造函数为 myProp 设置一个值:

public MyClass (int myProp) { this.MyProp = myProp; }

Is the constructor always immune to property accessor specifications?构造函数是否总是不受属性访问器规范的影响? Are they valid only after the constructor runs?它们仅在构造函数运行后才有效吗?

When you create an auto-property the compiler automatically generates backing fields to support it.创建自动属性时,编译器会自动生成支持字段来支持它。 In the case of a readonly ( get only) property this is still the case.对于只读(仅get )属性,情况仍然如此。 Being able to assign to a get -only property in the constructor is simply syntactic sugar supported by the compiler.能够在构造函数中分配给get -only 属性只是编译器支持的语法糖 When you assign to the property, the compiler translates the code so that it assigns to the backing field instead.当您分配给属性时,编译器会转换代码,以便它分配给支持字段

For example, assume your constructor:例如,假设您的构造函数:

public MyClass(int myProp)
{ 
    this.MyProp = myProp;
}

This is translated by the compiler to something akin to the following:这由编译器翻译成类似于以下内容:

public MyClass(int myProp)
{ 
    this._myPropBackingField = myProp;
}

The fact that you have no set accessor then prevents you from assigning to the property everywhere else.您没有set访问器的事实会阻止您在其他任何地方分配该属性。

In reality, the backing field recieves an "unspeakable" name that is illegal c# (but valid IL) thus preventing you from attempting to use the field directly.实际上,支持字段会收到一个“不可描述”的名称,该名称是非法的 c#(但有效的 IL),因此会阻止尝试直接使用该字段。 Your example actually looks like the following after the compiler has done its job:在编译器完成工作后,您的示例实际上如下所示:

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

Note that the constructor is actually assigning to the backing field <MyProp>k__BackingField directly rather than indirectly via the property's set ter (since after all one does not exist).请注意,构造函数实际上是直接分配给支持字段<MyProp>k__BackingField ,而不是通过属性的set ter 间接分配(因为毕竟不存在)。

See this SharpLab example .请参阅此SharpLab 示例

Just think if the constructor is not allowed to initialize these values then what is the use of these values?试想如果不允许构造函数初始化这些值,那么这些值有什么用? It will always be the datatype default value like for int it will be 0. By using only get means we will not allow to change the value once it's initialized.它始终是数据类型的默认值,如 int 它将为 0。通过仅使用 get 意味着我们将不允许在初始化后更改该值。

You can use readonly also, and it is thread-safe by default.您也可以使用readonly ,默认情况下它是线程安全的。 but when you use a private set you have to handle the thread-safety explicitly.但是当您使用私有集时,您必须明确处理线程安全。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM