15

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 : Is method hiding ever a good idea (thanks Scott), the most common scenario seems to be the emulation of covariant return type.

Machavity
  • 30,841
  • 27
  • 92
  • 100
Pragmateek
  • 13,174
  • 9
  • 74
  • 108

7 Answers7

10

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
  • 155,851
  • 29
  • 291
  • 343
  • 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. – Pragmateek Aug 13 '10 at 12:37
  • 1
    @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 Aug 13 '10 at 12:46
  • You're right, I, too, do not see any interesting use case where it should be needed. – Pragmateek Aug 13 '10 at 13:04
  • 1
    @Serious, there are a few use cases for it. See http://stackoverflow.com/questions/2663274/is-method-hiding-ever-a-good-idea – ScottS Aug 13 '10 at 15:42
  • @Scott, thanks a lot for this link, I've updated the initial post accordingly. – Pragmateek Aug 16 '10 at 09:53
6

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
  • 37,459
  • 12
  • 63
  • 82
  • 4
    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 Aug 13 '10 at 12:57
  • Thanks for these great examples. – Pragmateek Aug 13 '10 at 13:02
  • @Fredrik: oops, thanks. For some reason I completely overlooked that. You are indeed correct and the warning is the only difference. – Paul Ruane Aug 16 '10 at 09:57
  • @PaulRuane Would you be open to updating the answer to include Fredrik's insight? – Colm Bhandal May 28 '20 at 17:47
5

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
  • 922,412
  • 146
  • 1,693
  • 2,536
2

An example following Fredrik's answer. I want to have an interface that represents a method to get an entity by id. I then want both a WCF service and some other standard repository able to be used as that interface. In order to play with WCF, I need to decorate my interface with attributes. From an intent standpoint, I don't want to decorate my interface with WCF stuff when it's not going to be used via only WCF, so I need to use new. Here's the code:

public class Dog
{
    public int Id { get; set; }
}

public interface IGetById<TEntity>
{
    TEntity GetById(int id);
}

public interface IDogRepository : IGetById<Dog> { }

public class DogRepository : IDogRepository
{
    public Dog GetById(int id)
    {
        throw new NotImplementedException();
    }
}

[ServiceContract]
public interface IWcfService : IGetById<Dog>
{
    [OperationContract(Name="GetDogById")]
    new Dog GetById(int id);
}
greyalien007
  • 510
  • 4
  • 13
  • Interesting, is it from a real use-case? – Pragmateek Dec 01 '13 at 22:47
  • Yep, all of my repository retrieval methods are abstracted behind an interface (one per method). Then any object that needs to support some sort of retrieval can implement the interface. Some of those are WCF services which results in the above code. – greyalien007 Dec 02 '13 at 16:23
1

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
  • 8,455
  • 3
  • 30
  • 50
1

Having read through these answers, they explain pretty well what the new operator does, but I don't see any clear answer to this part of the OP's question:

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

In summary, it all boils down to testability and reuse. By splitting up interfaces into smaller chunks, and adhering to the Interface Separation Principle, we can make users of our classes minimally dependent on irrelevant detail and maximally decoupled, which provides us with more reusability options and an easier time when it comes to testing.

In general, the new operator comes into play here when we need to branch our interface type-hierarchy in a way where method collisions are unavoidable. That all sounds a bit abstract and it's hard to explain, so I created what I believe is a minimal example where we want to split our interface type hierarchy into two, while there's a common shared method. I put the code on .NET fiddle:

https://dotnetfiddle.net/kRQpoU

Here it is again:

using System;

public class Program
{
    public static void Main()
    {
        //Simple usage
        var simpleCuboid = new MockCuboidSimple();
        var heightUser = new HeightUserEntangled();
        var volumeUser = new VolumeUserEntangled();
        Console.WriteLine("*** Simple Case ***");
        Console.WriteLine(heightUser.PrintHeight(simpleCuboid));
        Console.WriteLine(volumeUser.PrintVolume(simpleCuboid));

        //Smart usage - the same behaviour, but more testable behind the scenes!
        var smartCuboid = new MockCuboidSmart();
        var heightUserSmart = new HeightUserSmart();
        var volumeUserSmart = new VolumeUserSmart();
        Console.WriteLine("*** smart Case ***");
        Console.WriteLine(heightUserSmart.PrintHeight(smartCuboid));
        Console.WriteLine(volumeUserSmart.PrintVolume(smartCuboid));
    }
}

//Disentangled

class VolumeUserSmart
{
    public string PrintVolume(IThingWithVolume volumeThing)
    {
        return string.Format("Object {0} has volume {1}", volumeThing.Name, volumeThing.Volume);
    }       
}

class HeightUserSmart
{
    public string PrintHeight(IThingWithHeight heightThing)
    {
        return string.Format("Object {0} has height {1}", heightThing.Name, heightThing.Height);
    }       
}

class MockCuboidSmart : ICuboidSmart
{
    public string Name => "Mrs. Cuboid";
    public double Height => 3.333;
    public double Width => 31.23432;
    public double Length => 123.12;
    public double Volume => Height * Width * Length;
}

interface ICuboidSmart : IThingWithHeight, IThingWithVolume
{
    //Here's where we use new, to be explicit about our intentions
    new string Name {get;}
    double Width {get;}
    double Length {get;}
    //Potentially more methods here using external types over which we have no control - hard to mock up for testing
}

interface IThingWithHeight
{
    string Name {get;}
    double Height {get;}
}   

interface IThingWithVolume
{
    string Name {get;}
    double Volume {get;}
}

//Entangled

class VolumeUserEntangled
{
    public string PrintVolume(ICuboidSimple cuboid)
    {
        return string.Format("Object {0} has volume {1}", cuboid.Name, cuboid.Volume);
    }       
}

class HeightUserEntangled
{
    public string PrintHeight(ICuboidSimple cuboid)
    {
        return string.Format("Object {0} has height {1}", cuboid.Name, cuboid.Height);
    }       
}

class MockCuboidSimple : ICuboidSimple
{
    public string Name => "Mrs. Cuboid";
    public double Height => 3.333;
    public double Width => 31.23432;
    public double Length => 123.12;
    public double Volume => Height * Width * Length;
}

interface ICuboidSimple
{
    string Name {get;}
    double Height {get;}
    double Width {get;}
    double Length {get;}
    double Volume {get;}
    //Potentially more methods here using external types over which we have no control - hard to mock up for testing
}

Notice that VolumeUserSmart and HeightUserSmart only depend on fragments of the ICuboidSmart interface that they care about, namely IThingWithHeight and IThingWithVolume. This way, they can be maximally reused, e.g. for shapes other than cuboids, and also can be more easily tested. The last point is, I find in practice, crucial. It's much easier to mock up an interface with fewer methods, especially if the methods in the main interface type contain references to types that we don't control. Of course, one can always get around this with a mocking framework, but I prefer to keep the code clean at its core.

So where does the new keyword fit in here? Well, since VolumeUserSmart and HeightUserSmart both need access to the Name property, we must must declare it in both IThingWithHeight and IThingWithVolume. And thus we must redeclare it in the sub-interface ICuboidSmart, or else we'll get a compiler error complaining about ambiguity. What we're doing in that case is hiding the two versions of Name defined in IThingWithHeight and IThingWithVolume that would otherwise collide. And, like other answers point out, though we don't have to use new here, we should, to be explicit about our intentions to hide.

Colm Bhandal
  • 3,343
  • 2
  • 18
  • 29
0

I use it almost in every my interface. Look here:

interface ICreature
{
    /// <summary>
    ///     Creature's age
    /// </summary>
    /// <returns>
    ///     From 0 to int.Max
    /// </returns>
    int GetAge();
}

interface IHuman : ICreature
{
    /// <summary>
    ///     Human's age
    /// </summary>
    /// <returns>
    ///     From 0 to 999
    /// </returns>
    new int GetAge();
}

It is absolutely normal to have an inherited member with lesser requirements but larger obligations. LSP is not violated. But if so, where to document the new contract?

astef
  • 8,575
  • 4
  • 56
  • 95
  • 1
    Not sure in this case creating a `new` method is the most appropriate way. For me having a different range of ages should be managed internally by the implementations, that would each document their invariants. And if I continue with your example, not all the humans have the same range: the patriarchs have indeed a 0-999 range but since then the range is more 0-149. As you say this kind of contract cannot be described by the language or the runtime themselves, but you can use metadata like `System.ComponentModel.DataAnnotations.RangeAttribute`. – Pragmateek May 18 '14 at 09:57
  • 1
    It's not about ranges, it's about requirements and obligations. Ranges are just the simplest examples of requirements. Managing those req/obl in implementations results in duplicated/not-reusable code. It is not obvious in such a simple example, but it is inevitable in big projects with deep hierarchies. About not all humans have the same range - it depends on your domain. In my universe of abstractions - it is true. In yours - make your own abstraction ;) – astef May 18 '14 at 14:20
  • Yes but not all requirements should be expressed this way. To take another example if I have an interface `Vehicle` with a `getNumberOfWheels` method there is no reason to redefine a new method because a bike has 2 and a car 4. Redefining a new method is important if they do something functionnaly different. – Pragmateek May 18 '14 at 15:23
  • 1
    Yeah, in case of `IBike` there's no reason to redefine this method, if you can live with `IVehicle`'s wide contract with no problems. Anyway, you'll implement this method in a `class Bike : IBike` where you can specify new, stricter obligations, because each class has it's own contract too. – astef May 19 '14 at 07:18
  • 1
    This example doesn't make sense. The interface `IHuman` is not doing anything to enforce stricter requirements. In fact, if you removed `new int GetAge()` from `IHuman` there would be zero consequences to the code. This class would be the same either way: `public class Human : IHuman { public int GetAge() { return 0; } } ` – Dru Steeby Nov 26 '19 at 15:47
  • @DruSteeby I agree that the example doesn't make sense in this case, because the inheritance tree is just a single line. But I'm not sure that there are zero consequences to the code. By hiding the base interface's method, the sub-interface allows classes the option of implementing the method for the two interfaces separately. Even though practically this is never what you want (otherwise just call them different names) I believe it's a subtle point – Colm Bhandal May 28 '20 at 17:58