Kent Boogaart
Kent Boogaart

Reputation: 178740

Adding accessor to interface property allowed, but not to abstract property

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

Answers (5)

Sofian Hnaide
Sofian Hnaide

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

supercat
supercat

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

Chris Shain
Chris Shain

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

Servy
Servy

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

davisoa
davisoa

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

Related Questions