C#没有setter的属性 - 它如何从构造函数中设置?
你怎么能从构造函数中设置一个只能得到的自动属性?下面的代码显示了如何从构造函数中设置属性,但使用反射显示幕后真的没有setter。如果setter方法甚至不存在于IL中,它如何从构造函数调用中设置?C#没有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
真的发出 “无法形容的名字” 即止跌不是有效的C#标识符。
不仅仅是一个彻底的答案,而是来自Jon Skeet本人!令人惊叹的,谢谢:) – thisextendsthat
有趣的是,在'vb.net'你可以通过向属性名称_Thing'添加下划线来访问该“生成”字段,甚至改变值:)。 – Fabio
@Fabio:喔。幸运的是,在C#中,其名称为'
因为只读属性应在同一时间或其他指定,否则其价值将永远是该类型的默认值,这将是完全无用的。
这是构造函数用于(除了其他明显的原因外),将值分配给只读字段。
我的问题是_how_是否发生,如果setter方法不存在,在IL中?在封面下,构造函数如何设置调用属性的实际工作。 – thisextendsthat
只读属性(仅获取)具有支持readonly
的字段,您可能知道该字段只能在构造函数中设置。
因此,当你有object Property { get; }
这相当于
private readonly object _property;
public object get_Property(){return _property;}
和编译器知道,如果你在构造函数中设置的属性设置现场直接
非抽象的自动性能始终使用后台字段。设置类内的属性被转换为设置后台字段。活动以类似的方式进行。 – IllidanS4