By definition, private
members are not overridable.
If you want the setter to be overridable, you can mark it protected
instead of private
.
private abstract class InheritanceTest
{
public virtual object Property
{
get { return null; }
protected set { }
}
public class Child : InheritanceTest
{
public override object Property
{
get { return null; }
protected set { base.Property = null; }
}
}
}
To more specifically answer your question as to why:
Understand that when your C# code is compiled to IL code, there actually ends up being 3 things for 1 property.
- The
Property
property itself.
- A method named
get_Property()
which is the getter.
- A method names
set_Property()
which is the setter.
In your code, you have told .NET that "I want a virtual
property. It then cascades that access level to the getter and setter methods. Actually, in IL code, properties don't specify virtual
at all.
For the C# code:
public virtual object Property { get; set; }
The generated IL code is:
.property instance object Property() { ... }
.method public hidebysig newslot specialname virtual
instance object get_Property() cil managed
{ ... }
.method public hidebysig newslot specialname virtual
instance object set_Property() cil managed
{ ... }
Note that the public
and virtual
keywords are applied to both the getter and the setter methods, but not the property itself.
Now, by changing your C# code to:
public virtual object Property { get; private set; }
You have told .NET that you want your getter and setter methods to be virtual... however, then it runs into private set
, and that access level overrides the public
and virtual
access level, for the setter method. So, the generated IL code becomes:
.property instance object Property() { ... }
.method public hidebysig newslot specialname virtual
instance object get_Property() cil managed
{ ... }
.method private hidebysig newslot specialname
instance object set_Property() cil managed
{ ... }
Note that now set_Property()
is private
, and no longer virtual
. It is actually impossible to have a private virtual
in .NET, because it doesn't make sense... that is like trying to say "no other class can see this... but derived classes can override this thing, which they can't see or access" which doesn't make sense. Derived classes can't override what they can't even see.
The protected
keyword is the proper replacement in this case, because it tells .NET "Only myself and derived classes can see or access this, and derived classes can override this property."
So I guess the "short" answer would have just been "because things can't be private
and virtual
in .NET, so the compiler takes the more restricted access level that you gave it.
Also, IMO the error message is pretty correct.
'Program.InheritanceTest.Child.Property.set': cannot override inherited member 'Program.InheritanceTest.Property.set' because it is not marked virtual, abstract, or override
Note that it is saying 'Program.InheritanceTest.Property.set'
so the ".set" at the end is referring to the eventual set_Property()
method, not the Property
property. And the set_Property()
method is marked private
only, because the .NET compiler saw that, and removed virtual
from that method, for the reason mentioned above. I suppose it would make some sense to have a compiler warning or something saying that "virtual will be ignored for 'set'".
Hopefully that makes more sense...