没有setter的C#属性 - 如何从构造函数中设置?

时间:2017-09-23 15:56:45

标签: c# cil

为什么你可以从构造函数中设置get-only auto-property?下面的代码显示了如何从构造函数设置属性,但使用反射显示在幕后确实没有一个setter。如果setter方法甚至不存在于IL中,它是如何从构造函数调用中设置的?

void Main()
{
    var obj = new GetOnlyProperty("original value");
    Console.WriteLine(obj.Thing); //works, property gets set from ctor

    //get the set method with reflection, is it just hidden..?
    //nope, null reference exception
    typeof(GetOnlyProperty)
        .GetProperty("Thing", BindingFlags.Instance | BindingFlags.Public)
        .GetSetMethod()
        .Invoke(obj, new object[]{"can't set me to this, setter doen't exist!"});
}

public class GetOnlyProperty
{
    public string Thing { get; }

    public GetOnlyProperty(string thing)
    {
        Thing = thing;
    }
}

3 个答案:

答案 0 :(得分:19)

编译器将只读自动实现的属性转换为只读字段和只读属性。构造函数中对属性的赋值将编译为基础字段的赋值。

所以你的代码在这里:

public class GetOnlyProperty
{
    public string Thing { get; }

    public GetOnlyProperty(string thing)
    {
        Thing = thing;
    }
}

编译成IL,就像你写的那样:

public class GetOnlyProperty
{
    private readonly string _thing;
    public string Thing => _thing;

    public GetOnlyProperty(string thing)
    {
        _thing = thing;
    }
}

...除了_thing确实给出了一个“不可言喻的名称”,它不是一个有效的C#标识符。

答案 1 :(得分:2)

只读属性(仅限get)有一个支持readonly字段,您可能知道,只能在构造函数中设置。

因此当你有object Property { get; }

这转化为

private readonly object _property;
public object get_Property(){return _property;}

并且编译器知道如果在构造函数中设置属性以直接设置字段

答案 2 :(得分:0)

因为应该一次指定只读属性,否则它的值将始终是该类型的默认值,并且它将完全无用。

这是构造函数用于(除了其他明显的原因),为只读字段赋值。