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

没有setter的C#属性-如何从构造函数中设置它?,c#,cil,C#,Cil,为什么可以从构造函数中设置“仅获取自动”属性?下面的代码显示了如何从构造函数设置属性,但是使用反射表明在幕后确实没有setter。如果在IL中甚至不存在setter方法,那么如何从构造函数调用中设置它 void Main() { var obj = new GetOnlyProperty("original value"); Console.WriteLine(obj.Thing); //works, property gets set from ctor //get

为什么可以从构造函数中设置“仅获取自动”属性?下面的代码显示了如何从构造函数设置属性,但是使用反射表明在幕后确实没有setter。如果在IL中甚至不存在setter方法,那么如何从构造函数调用中设置它

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

因为只读属性应该在某个时间分配,否则其值将始终是该类型的默认值,并且将完全无用


这就是构造函数为只读字段赋值的目的(除其他明显原因外)。

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

所以你的代码在这里:

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;
    }
}
。。。除了
\u thing
实际上被赋予了一个“无法说出的名称”,该名称不是有效的C标识符。

只读属性(get-only)有一个backing
readonly
字段,您可能知道,该字段只能在构造函数中设置

因此,当您拥有
对象属性{get;}

这意味着

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

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

我的问题是,如果setter方法不存在,在IL中如何实现?构造函数如何设置对属性的调用,实际上是如何工作的,这不仅是一个彻底的答案,而且来自Jon Skeet本人!令人惊讶,谢谢:)有趣的是,在
vb.net
中,您可以通过在属性名
\u Thing
中添加下划线来访问“生成”字段,甚至可以更改值:)。@Fabio:Yikes。幸运的是,在C#中,它的名称类似于
k_ubackingfield
,而
使其作为标识符无效。非抽象自动属性始终使用BackingField。在类内设置属性将转换为设置支持字段。活动以类似的方式进行。