在覆盖虚拟自动实现的属性时,是否仍会为匿名支持字段创建?

时间:2011-06-20 21:01:11

标签: c# .net compiler-construction c#-3.0

病态的好奇心。说我有这种层次结构:

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关键字提供的相同成员隐藏功能,我必须得出结论,支持字段无论使用何时都会创建。

我猜一个相关的问题可能是“是否为从未访问的自动实现的属性创建了支持字段?”相同的基本论点,相同的结论。

3 个答案:

答案 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