I came across a behavior that surprises me. Given the following two classes:
class Parent
{
public virtual bool Property { get; set; }
}
class Child : Parent
{
public override bool Property { get => base.Property; }
}
I can write code like this:
Child child = new Child();
child.Property = true; // this is allowed
The IDE makes it confusing, too, because, while it allows the assignment, it also indicates that the overridden property is read-only:
Furthermore, this override is only allowed when I'm using the base class' getter:
What is going on here?
I'll take a crack at this.
It looks like this may just be a bug with Intellisense, where it is unable to find the base implementation of an auto-property. The code is valid and makes sense - here's another way to express your example.
Child child = new Child();
child.SetProperty(true);
class Parent
{
private bool _property;
public virtual bool GetProperty() => _property;
public virtual void SetProperty(bool value) => _property = value;
}
class Child : Parent
{
public override bool GetProperty() => base.GetProperty();
}
With this representation, it's now obvious why overriding GetProperty is fine. Here's the relevant IL for your code:
Main:
IL_0000: newobj Child..ctor
IL_0005: ldc.i4.1
IL_0006: callvirt Parent.set_Property
IL_000B: ret
Parent.get_Property:
IL_0000: ldarg.0
IL_0001: ldfld Parent.<Property>k__BackingField
IL_0006: ret
Parent.set_Property:
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: stfld Parent.<Property>k__BackingField
IL_0007: ret
Parent..ctor:
IL_0000: ldarg.0
IL_0001: call System.Object..ctor
IL_0006: ret
Child.get_Property:
IL_0000: ldarg.0
IL_0001: call Parent.get_Property
IL_0006: ret
Child..ctor:
IL_0000: ldarg.0
IL_0001: call Parent..ctor
IL_0006: ret
And here's my version:
Main:
IL_0000: newobj Child..ctor
IL_0005: ldc.i4.1
IL_0006: callvirt Parent.SetProperty
IL_000B: ret
Parent.GetProperty:
IL_0000: ldarg.0
IL_0001: ldfld Parent._property
IL_0006: ret
Parent.SetProperty:
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: stfld Parent._property
IL_0007: ret
Parent..ctor:
IL_0000: ldarg.0
IL_0001: call System.Object..ctor
IL_0006: ret
Child.GetProperty:
IL_0000: ldarg.0
IL_0001: call Parent.GetProperty
IL_0006: ret
Child..ctor:
IL_0000: ldarg.0
IL_0001: call Parent..ctor
IL_0006: ret
Note that this is different than public override bool Property { get; }
, being shorthand for instructing the compiler to generate a single getter override for a backing property of the same name, with no mention of the preexisting setter. Somebody experienced with the actual spec will definitely be able to offer more information around this, however.
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