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

C# Property with no setter - how can it get set from constructor?

你怎么能从构造函数中设置一个只读自动属性?下面的代码显示了如何从构造函数中设置 属性,但使用反射显示幕后确实没有 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;
    }
}

...除了 _thing 确实被赋予了一个 "unspeakable name",这不是有效的 C# 标识符。

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

因此当你有 object Property { get; }

这转化为

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

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