都是匿名的支持字段仍然是虚拟自动实现的属性创建他们重写时?都是、重写、仍然是、字段

2023-09-04 08:31:40 作者:失眠梦°Triste

病态的好奇心。说我有这样的层次:

Morbid curiosity. Say I have this hierarchy:

class Base {
  public virtual int Field { get; set; }
}

class Derived : Base {
  int _field;
  public override int Field { get { return _field; } set { _field = value; } }
}

如果我实例基本,编译器会奇迹般地创造了字段属性支持字段。

If I instantiate Base, the compiler will magically create a backing field for the Field property.

因此​​,考虑到导出不引用的基本实现,并支持字段获得创建时派生是实例化?难道这决定在C#规格,还是留给编译器实现?

So, given that Derived does not reference the base implementation, does the backing field get created when Derived is instantiated? Is this dictated in the C# spec, or left to compiler implementations?

更新

原来,该规范确实明确说明自动实现的属性都与隐性实施  支持字段。(10.7.3节),没有提到我的具体问题,假设字藏有指所提供的相同的成员隐藏功能关键字,我必须得出这样的结论支持字段总是创建不管用。

Turns out that the specification does indeed specifically state that automatically-implemented properties are implemented with a "hidden backing field". (Sec 10.7.3) Nothing is said of my specific question. Assuming the word "hidden" there refers to the same member-hiding functionality provided by the new keyword, I must conclude that the backing field is always created regardless of use.

我想一个相关的问题可能是对于那些从未访问的自动实现的属性创建一个支持字段?相同的基本参数,同样的结论。

I guess a related question might be "Is a backing field created for a auto-implemented property that is never accessed?" Same underlying argument, same conclusion.

推荐答案

此示例程序演示了创建支持字段。以 GetFields通话返回的支持字段的Int32<现场> k__BackingField 在下面的例子。您可以设置并通过反射得到这个字段的值,而不是通过导出实例。你也可以看到,二传上的派生类中声明,当你通过反射更新字段不叫。

This sample program demonstrates that the backing field is created. The call to GetFields returns a backing field of Int32 <Field>k__BackingField in the example below. You can set and get the value of this field via reflection, but not through the derived instance. You can also see that the setter declared on the Derived class is not called when you update the field via reflection.

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

这是写出来与从调用返回 GetFields 字段信息例如20值说明该支持字段创建。

The 20 value that is written out along with the FieldInfo instance that is returned from the call to GetFields demonstrates that the backing field is created.