Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

interface inheritance without hiding

Tags:

c#

If I write class, then all ok

class C
{
    protected int _attr;
    int attr { get { return _attr; } }
}

class CWithSet : C
{
    int attr { set { _attr = value; } }
}

But, if I write interface

interface I
{
    int attr { get; }
}

interface IWithSet : I
{
    int attr { set; }
}

then I have warring: "'IWithSet.attr' hides inherited member 'I.attr'. Use the new keyword if hiding was intended."

How to write, so as not to get warning?

like image 796
SkyN Avatar asked Dec 29 '22 09:12

SkyN


2 Answers

From the C# Specification: The inherited members of an interface are specifically not part of the declaration space of the interface. Thus, an interface is allowed to declare a member with the same name or signature as an inherited member. When this occurs, the derived interface member is said to hide the base interface member. Hiding an inherited member is not considered an error, but it does cause the compiler to issue a warning. To suppress the warning, the declaration of the derived interface member must include a new modifier to indicate that the derived member is intended to hide the base member. (Interface members) The correct implementation is:

interface IWithSet : I
{
    new int attr { get; set; }
}
like image 179
Eric Mickelsen Avatar answered Jan 14 '23 01:01

Eric Mickelsen


You might want to consider whether it's worth redefining the semantics of your interfaces. What I mean is, it might make sense to just have a separate write-only interface in addition to the read-only one you've defined as "I".

Here's an example:

interface IReadOnly
{
    int Attr { get; }
}

interface IWriteOnly
{
    int Attr { set; }
}

interface I : IReadOnly, IWriteOnly
{
}

class CReadOnly : IReadOnly
{
    protected int _Attr;
    public int Attr
    {
        get { return _Attr; }
    }
}

class C : CReadOnly, I
{
    public int Attr
    {
        get { return base.Attr; }
        set { _Attr = value; }
    }
}

EDIT: I changed the get portion of the C.Attr property to be return base.Attr instead of return _Attr; in order to be more consistent with the code example in the original question. I also think that is more correct, since you may have more complicated logic defined in CReadOnly.Attr that you do not want to duplicate.

Some of the interfaces and classes have been renamed from the original example. "I" became "IReadOnly", and "IWithSet" became "I". "C" became "CReadOnly", and "CWithSet" became "C".

This compiled for me with no warnings.

EDIT: This compiled for me with no warnings regarding the interface members. I did get 1 warning regarding the C class' Attr property hiding the CReadOnly class' property, but this should be entirely expected, since hiding/shadowing is what's going on in my example. One weird thing: I could swear that I compiled (and ran!) this code a couple of times and saw 0 warnings. That confused me at the time, but I let it go...yet now I'm seeing the 1 warning as I would expect. Maybe just a compiler glitch.

like image 25
Dr. Wily's Apprentice Avatar answered Jan 14 '23 01:01

Dr. Wily's Apprentice