Reputation: 178740
Why is it that the following is legal C#:
public interface ISomeInterface
{
int SomeProperty
{
get;
}
}
public class SomeClassImplementingInterface : ISomeInterface
{
public int SomeProperty
{
get { return 32; }
protected set {}
}
}
but this is not:
public abstract class SomeAbstractClass
{
public abstract int SomeProperty
{
get;
}
}
public class SomeClassExtendingAbstractClass : SomeAbstractClass
{
public override int SomeProperty
{
get { return 32; }
protected set {}
}
}
The latter results in the following compile-time error:
'InterfaceAbstractTest.SomeClassExtendingAbstractClass.SomeProperty.set': cannot override because 'InterfaceAbstractTest.SomeAbstractClass.SomeProperty' does not have an overridable set accessor InterfaceAbstractTest
What is the reasoning for not disallowing the latter whilst allowing the former?
Upvotes: 6
Views: 4808
Reputation: 2364
This is by design. I am quoting from the C# language specs:
An overriding property declaration must specify the exact same accessibility modifiers, types and name as the inherited property, if the inherited property has only a single accessor (i.e.,... ready only or write-only), the overriding property must include only that accessor.
The reason behind that decesion could be because the interfaces are more flexibly type of contracts than abstract classes. Interfaces cares only about the least common denominator rather than the whole implementation. I think there are good reasons to choose one design over the other.
Upvotes: 2
Reputation: 81197
What is necessary is to both override the existing property and shadow it with a new read-write one. Unfortunately, .net does not provide any means of both overriding and shadowing a member within a single class. The best one can do is probably to have the abstract base class define a concrete non-virtual read-only property whose getter calls an abstract function. A derived class can then shadow the property with a non-virtual read-write function which calls the same function in its getter, and a new abstract or virtual function in its setter.
Upvotes: 0
Reputation: 51349
Because a caller using the interface only cares that an implementer of the interface at least implements the interface's definition, as @davisoa states, whereas SomeAbstractClass
in your example defines a public contract which states exactly the type, accessibility, and (for properties) readability/writability of members.
If you use reflection to get the PropertyInfo of SomeProperty
(from either the base or child class), it needs to resolve that information from somewhere. Allowing the child class to change the readability/writability would be as much of a contract violation as a change in return type or argument list.
Imagine for instance:
SomeAbstractClass sc = new SomeClassExtendingAbstractClass();
PropertyInfo pi = sc.GetType().GetProperty("SomeProperty");
Console.Out.WriteLine(pi.CanWrite); // What should be printed here?
Upvotes: 3
Reputation: 203836
You're trying to override a set operator that doesn't exist. Either define a set portion of the property in the abstract class, or don't try to define one in the concrete class. Since you have the set as protected in the concrete class, my guess is what you want to do is make a protected set operator in the abstract definition.
Upvotes: 1
Reputation: 5439
This is because the Interface implementation is making a promise that there will be a property SomeProperty
that you can "Get".
The abstract class implementation is making a promise that it's child classes will provide an implementation of a property SomeProperty
with a public get method.
In the end, the base class is defining something that must be overridden, whereas the interface is defining a contract.
Upvotes: 2