views:

127

answers:

4

Hello,

it's possible to mark a method declaration in an interface as "new" but does it have any "technical" sense or is it just a way to explicitly state that the declaration cannot override a previous one ?

For example :

interface II1
{
    new void F();
}

interface II2 : II1
{
    new void F();
}

is valid (the C# 4.0 compiler does not complain) but does not appear to be different from :

interface II1
{
    void F();
}

interface II2 : II1
{
    void F();
}

Thanks in advance for any information.

EDIT: do you know a scenario where hiding in an interface would be useful ?

EDIT: According to this link : http://stackoverflow.com/questions/2663274/is-method-hiding-ever-a-good-idea (thanks Scott), the most common scenario seems to be the emulation of covariant return type.

+5  A: 

The second example issues the following compiler warning:

'II2.F()' hides inherited member 'II1.F()'. Use the new keyword if hiding was intended.

I'd say the difference of using the new keyword is exactly that: showing intention.

Fredrik Mörk
Thanks for your answer.So it won't affect the way the interfaces can be used ?I'll edit the initial post to clarify this.
Serious
@Serious: no, the only difference is the compiler warning. I would recommend using the `new` keyword in order to be clear. Well, no, I would actually recommend against method hiding in general since I find it confusing, but if *needed*, use the `new` keyword.
Fredrik Mörk
You're right, I, too, do not see any interesting use case where it should be needed.
Serious
@Serious, there are a few use cases for it. See http://stackoverflow.com/questions/2663274/is-method-hiding-ever-a-good-idea
ScottS
@Scott, thanks a lot for this link, I've updated the initial post accordingly.
Serious
+5  A: 

The two are very different. By using 'new' you are creating a new inheritance chain. This means any implementations of II2 will need to realize both versions of F(), and the actual one you end up calling will depend upon the type of the reference.

Consider the following three realizations:

    class A1 : II1
    {
        public void F()
        {
            // realizes II1.F()
        }
    }

    class A2 : II2
    {
        void II1.F()
        {
            // realizes II1.F()
        }

        void II2.F()
        {
            // realizes II2.F()
        }
    }

    class A3 : II2
    {
        public void F()
        {
            // realizes II1.F()
        }

        void II2.F()
        {
            // realizes II2.F()
        }
    }

If you have a reference to A2, you will not be able to call either version of F() without first casting to II1 or II2.

A2 a2 = new A2();
a2.F(); // invalid as both are explicitly implemented
((II1) a2).F(); // calls the II1 implementation
((II2) a2).F(); // calls the II2 implementation

If you have a reference to A3, you will be able to call the II1 version directly as it is an implicit implentation:

A3 a3 = new A3();
a3.F(); // calls the II1 implementation
((II2) a3).F(); // calls the II2 implementation
Paul Ruane
@Paul: note that there is no difference in the compiled code between the two examples given in the question. The difference that you explain is the effect of method hiding, but it happens regardless of using the `new` keyword or not.
Fredrik Mörk
Thanks for these great examples.
Serious
@Fredrik: oops, thanks. For some reason I completely overlooked that. You are indeed correct and the warning is the only difference.
Paul Ruane
+1  A: 

I know of one good use for this: you have to do this to declare a COM interface that's derived from another COM interface. It is touched upon in this magazine article.

Fwiw, the author completely misidentifies the source of the problem, it has nothing to do with an 'inheritance tax'. COM simply leverages the way a typical C++ compiler implements multiple inheritance. There's one v-table for each base class, just what COM needs. The CLR doesn't do this, it doesn't support MI and there's only ever one v-table. Interface methods are merged into the v-table of the base class.

Hans Passant
Thanks for this good example.
Serious
+1  A: 

The new modifier is very simple, it just suppresses the compiler warning that is created when a method is hidden. If used on a method that does not hide another method a warning is generated.

From The C# Language Specification 3.0

10.3.4 The new modifier A class-member-declaration is permitted to declare a member with the same name or signature as an inherited member. When this occurs, the derived class member is said to hide the base class 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 class member can include a new modifier to indicate that the derived member is intended to hide the base member. This topic is discussed further in §3.7.1.2. If a new modifier is included in a declaration that doesn’t hide an inherited member, a warning to that effect is issued. This warning is suppressed by removing the new modifier.

ScottS