简体   繁体   中英

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

I wrote a class property with only get accessor, like:

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. However, somehow, I can set a value to myProp using a constructor like:

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. Being able to assign to a get -only property in the constructor is simply syntactic sugar supported by the compiler. 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.

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. 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).

See this SharpLab example .

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.

You can use readonly also, and it is thread-safe by default. but when you use a private set you have to handle the thread-safety explicitly.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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