Interface inheritance without hiding

If I write a class, then everything is ok

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

But if I write an interface

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

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

How to write so as not to receive warnings?

+4
source share
5 answers

Perhaps you should consider whether to redefine the semantics of your interfaces. I mean, it makes sense to just have a separate write interface in addition to the read-only interface, which you defined as "I."

Here is 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 receiving part of the C.Attr property as return base.Attr instead of return _Attr; to be more compatible with the sample code in the original question. I also think this is more correct, since you may have more complex logic defined in CReadOnly.Attr that you do not want to duplicate.

Some 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 without warning.

EDIT: This compiled for me without warnings about interface members. I received 1 warning regarding the class C property of the class hiding the CReadOnly class property, but this should be fully expected, as hiding / shadowing occurs in my example. One strange thing: I can swear that I compiled (and ran!) This code a couple of times and saw 0 warnings. It embarrassed me at that time, but I let it go ... but now I see warning 1, as you would expect. Maybe just a compiler crash.

+3
source

From the C # specification: Inherited interface members are not specifically part of the interface declaration space. Thus, an interface is allowed to declare a member with the same name or signature as an inherited element. When this happens, the derived interface member is said to hide the underlying interface element. Hiding the inherited element is not considered an error, but this leads to the compiler generating a warning. To suppress the warning, a declaration of a derived member of an interface must include the new modifier to indicate that the derived member is intended to hide the underlying element. ( Interface Elements ). Correct implementation:

 interface IWithSet : I { new int attr { get; set; } } 
+5
source

If you need separate attributes with the same name, use the new one. The warning is self-evident.

On the other hand, what you want seems to be more like:

 #pragma warning disable CS0108 interface IWithSet : I { int attr { get; set; } } #pragma warning restore CS0108 
+1
source

This may not be ideal, but one solution might be:

 interface IWithSet : I { void SetAttr(int value); } 
0
source

How about just:

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

The disadvantage is that IWithSet will always have both getter and setter, even if the recipient in 'I' is deleted:

 interface I { } 

If you define two interfaces with the assumption that "I" will always have a getter, then there is nothing wrong with this approach, this works fine in the hierarchy of interfaces designed to restrict access, and not to encapsulate the logic specific to (as a typical type structure reader / writer, where the author inherits all reader access to SAFE's assumption that the reader has read permission!).

0
source

All Articles