【问题标题】:C# Property with no setter - how can it get set from constructor?没有设置器的 C# 属性 - 如何从构造函数中设置它?
【发布时间】:2017-09-23 15:56:44
【问题描述】:

为什么你可以从构造函数中设置一个只获取的自动属性?下面的代码显示了如何从构造函数设置属性,但使用反射表明幕后确实没有设置器。如果在 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;
    }
}

【问题讨论】:

  • 非抽象自动属性始终使用支持字段。在类中设置属性被转换为设置支持字段。事件以类似的方式工作。

标签: c# cil


【解决方案1】:

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

所以你的代码在这里:

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# 标识符。

【讨论】:

  • 不仅仅是一个彻底的答案,而是来自 Jon Skeet 本人!太棒了,谢谢你:)
  • 有趣的是,在vb.net 中,您可以通过在属性名称_Thing 中添加下划线来访问“生成”字段,甚至可以更改值:)。
  • @法比奥:哎呀。幸运的是,在 C# 中,它被命名为 <Thing>k__BackingField,而 <> 使其作为标识符无效。
【解决方案2】:

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

因此当你有object Property { get; }

这翻译成

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

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

【讨论】:

    【解决方案3】:

    因为只读属性应该一次赋值,否则它的值将永远是该类型的默认值,完全没用。

    这就是构造函数的用途(除了其他明显的原因),将值分配给只读字段。

    【讨论】:

    • 我的问题是 如何 如果 setter 方法不存在,在 IL 中会发生这种情况吗?在幕后,构造函数对属性的 set 调用实际上是如何工作的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多