Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 487
Kent Boogaart Avatar asked Feb 20 '12 16:02

Kent Boogaart


3 Answers

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?
like image 163
Chris Shain Avatar answered Sep 24 '22 01:09

Chris Shain


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.

like image 41
davisoa Avatar answered Sep 24 '22 01:09

davisoa


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.

like image 23
Sofian Hnaide Avatar answered Sep 24 '22 01:09

Sofian Hnaide