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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With