Overriding an automatic property
since this
public int MyInt{ get; set;}
is equivalent to
private int _myInt;
public int MyInt{ get{return _myInt;} set{_myInt = value;} }
when you make the automatic property virtual
public virtual int MyInt{ get; set;}
and then override this property in a child class
public override int MyInt{ get{return someVar;} set{someVar = value;} }
does this child class now have an unwelcomed and hidden allocation of _myInt?
Short Answer: Yes, the Child
allocates all Base
class fields, so it still has the backing field allocated. However, you can't access it any other way than through Base.MyInt
property.
Long Answer:
Quick disassembly results.
Base
and Child
classes implementation:
public class Base
{
public virtual int MyInt { get; set; }
}
public class Child : Base
{
private int anotherInt;
public override int MyInt
{
get { return anotherInt; }
set { anotherInt = value; }
}
}
As you can see, the backing field exists within Base
class. However, it is private, so you can't access it from Child
class:
.field private int32 '<MyInt>k__BackingField'
And your Child.MyInt
property does not use that field. The property IL is:
.method public hidebysig specialname virtual
instance int32 get_MyInt () cil managed
{
// Method begins at RVA 0x2109
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldfld int32 ConsoleApplication2.Child::anotherInt
IL_0006: ret
} // end of method Child::get_MyInt
.method public hidebysig specialname virtual
instance void set_MyInt (
int32 'value'
) cil managed
{
// Method begins at RVA 0x2111
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: stfld int32 ConsoleApplication2.Child::anotherInt
IL_0007: ret
} // end of method Child::set_MyInt
Is uses anotherInt
field, as you could expect.
The only ways to access the '<MyInt>k__BackingField'
(indirectly, through Base.MyInt
property) are:
-
base.MyInt
from withinChild
class
It's not just equivalent its pretty much the actual implementation. The compiler rewrites your automatic properties in its precompile stage. Albeit the field name will be named something else.
As a result the behaviour will be identical to you creating the property manually.
Yes the hidden field will exist, however it will not be assigned to because your override doesn't call the base implementation.
if you changed the override to
public override int MyInt
{
get { return someVar; }
set {
someVar = value;
base.MyInt = value
}
}
Then the allocation would occur
Yes, just as if it was not defined as an automatic property.
The allocation is needed in the base class, because it still needs to exist and be useful. The base class has no knowledge of the existence of the derived class, and the derived class can use the backing field in its definition
If you have a base and derived class defined like:
public class Base
{
public virtual string Name {get; set;}
}
public class Derived : Base
{
private string _name;
public override string Name
{
get {
return _name;
}
set
{
//access the base property we are overriding
base.Name = value + " from derived";
_name = value;
}
}
}
You can use reflection to see that the backing field of the base class does indeed exist, and behaves as expected:
Type tbase = typeof(Base);
FieldInfo fi = tbase.GetField("<Name>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance);
Base b = new Base {Name = "Test"};
string baseValue = fi.GetValue(b).ToString();
Console.WriteLine(baseValue); //gives "Test";
Derived d = new Derived {Name = "Test" };
string derivedValue = fi.GetValue(d).ToString();
Console.WriteLine(derivedValue); //gives "Test from derived";
The name of the actual backing field is an undocumented implementation detail, so I wouldn't use it in any production code. (I got it by using LINQPad's IL View)