7

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.

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?

Update

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.

G-Wiz
  • 7,370
  • 1
  • 36
  • 47
  • 2
    I'd think so. `Base` has such a field (generally speaking) and `Derived` inherits from it, so it *should* have such a field as well. And if not (because it's unreachable or anything), that'd be just an optimization. –  Jun 20 '11 at 21:10
  • Right, but do we know that Base will always have that field? I can imagine many other ways auto-implemented properties can be implemented by the compiler, unless the C# Language Spec stipulates that auto-implemented properties are simply backed by a field of the same type. – G-Wiz Jun 20 '11 at 21:52
  • 1
    Ah, turns out that the specification does stipulate this. Section 10.7.3: "When a property is specified as an automatically implemented property, a hidden backing field is automatically available for the property, and the accessors are implemented to read from and write to that backing field." – G-Wiz Jun 20 '11 at 21:53

3 Answers3

2

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; } 
  }
}

The output of this program is:

Setter called.
10
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.

rsbarro
  • 27,021
  • 9
  • 71
  • 75
2

So, given that Derived does not reference the base implementation, does the backing field get created when Derived is instantiated?

Absolutely the backing field is created. Just because Derived doesn't use the backing field provided by Base, for an instance of Derived to be a Base, the field must exist. Imagine if we added the following method to Derived:

public int GetBaseField()
{
    return base.Field; // calls Base.get_Field(), which uses the base
                       // class's auto-generated backing property
}

This example needs to be valid; there's never a good reason to try to optimize away base class values that are unused in a derived class.

Adam Maras
  • 26,269
  • 6
  • 65
  • 91
  • A constraint in my question was that the `Derived` definition doesn't reference `base.Field`. In this specific case, there doesn't seem to be a need for the backing field. Obviously if there were a reference to `base.Field` in another `Derived` member, I would expect the backing field to be created. – G-Wiz Jun 20 '11 at 21:44
1

I would think it does. You can always reach this method through reflection, something the compiler can not predict at compile time, so it has to be compiled.

Same reason why private methods never called in code are still compiled: C# Compiler optimization - Unused methods

Community
  • 1
  • 1
InBetween
  • 32,319
  • 3
  • 50
  • 90
  • Good point, thanks. When I wrote the question I was coming from a slightly different angle, where auto-implemented properties are black-box language features, to be implemented as the compiler prefers. From that angle, your example differs because including private methods can be thought to carry more specific programmer intent than the use of the auto-implemented property abstraction. But I've since read the spec and see that auto-implemented properties must be implemented with a hidden backing field of the same type. – G-Wiz Jun 20 '11 at 22:00