病态的好奇心。说我有这种层次结构:
class Base {
public virtual int Field { get; set; }
}
class Derived : Base {
int _field;
public override int Field { get { return _field; } set { _field = value; } }
}
如果我实例化Base
,编译器会神奇地为Field
属性创建一个支持字段。
因此,鉴于Derived
未引用基本实现,是否在实例化Derived
时创建了支持字段?这是在C#规范中规定的,还是留给编译器实现?
更新
事实证明,规范确实明确规定自动实现的属性是使用“隐藏”实现的
支持字段“。(第10.7.3节)没有说明我的具体问题。假设”隐藏“一词指的是new
关键字提供的相同成员隐藏功能,我必须得出结论,支持字段无论使用何时都会创建。
我猜一个相关的问题可能是“是否为从未访问的自动实现的属性创建了支持字段?”相同的基本论点,相同的结论。
答案 0 :(得分:2)
此示例程序演示了创建了支持字段。对GetFields
的调用会在下面的示例中返回Int32 <Field>k__BackingField
的支持字段。您可以通过反射设置和获取此字段的值,但不能通过derived
实例获取。您还可以看到,当您通过反射更新字段时,未调用Derived
类上声明的setter。
void Main()
{
var derived = new Derived();
derived.Field = 10;
var fieldInfo = typeof(Base).GetFields(
BindingFlags.NonPublic | BindingFlags.Instance)[0];
fieldInfo.SetValue(derived, 20);
Console.WriteLine(derived.Field);
Console.WriteLine(fieldInfo.GetValue(derived));
}
public class Base {
public virtual int Field { get; set; }
}
public class Derived : Base {
int _field;
public override int Field
{
get { return _field; }
set { Console.WriteLine("Setter called."); _field = value; }
}
}
该程序的输出是:
Setter called.
10
20
与调用FieldInfo
时返回的GetFields
实例一起写出的20值表明已创建了支持字段。
答案 1 :(得分:1)
因此,假设Derived没有引用基本实现,那么在实例化Derived时是否会创建支持字段?
绝对会创建支持字段。仅仅因为Derived
不使用Base
提供的支持字段,对于Derived
到的实例 a Base
,该字段必须存在。想象一下,如果我们将以下方法添加到Derived
:
public int GetBaseField()
{
return base.Field; // calls Base.get_Field(), which uses the base
// class's auto-generated backing property
}
这个例子需要有效;尝试优化派生类中未使用的基类值是没有充分理由的。
答案 2 :(得分:0)
我认为确实如此。您总是可以通过反射来实现此方法,这是编译器无法在编译时预测的,因此必须进行编译。
为什么从未在代码中调用的私有方法仍然被编译的原因相同:C# Compiler optimization - Unused methods