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

thi*_*hat 10 c# cil

为什么你可以从构造函数设置一个get-only auto-property?下面的代码显示了如何从构造函数设置属性,但使用反射显示在幕后确实没有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;
    }
}
Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 25

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

所以你的代码在这里:

public class GetOnlyProperty
{
    public string Thing { get; }

    public GetOnlyProperty(string thing)
    {
        Thing = thing;
    }
}
Run Code Online (Sandbox Code Playgroud)

被编译成IL,就好像你写的:

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

    public GetOnlyProperty(string thing)
    {
        _thing = thing;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

  • 不仅仅是乔恩·斯基特本人的彻底回答!太棒了,谢谢你:) (3认同)
  • @法比奥:哎呀。幸运的是,在 C# 中,它的名称类似于 `<Thing>k__BackingField`,而 `<>` 使其作为标识符无效。 (2认同)