3

If I have two interfaces:

    interface IGrandparent
    {
        void DoSomething();
    }

    interface IParent : IGrandparent
    {
        void DoSomethingElse();
    }

then there are two implementations:

//only includes last interface from the inheritance chain
public class Child1 : IParent 
{
    public void DoSomething()
    {
        throw new NotImplementedException();
    }

    public void DoSomethingElse()
    {
        throw new NotImplementedException();
    }
}

// includes all the interfaces from the inheritance chain    
public class Child2 : IGrandparent, IParent     
{
    public void DoSomething()
    {
        throw new NotImplementedException();
    }

    public void DoSomethingElse()
    {
        throw new NotImplementedException();
    }
}

Are these two implementations identical? (except the class name)? Some people say there are something to do with "implicit and explicit implementation", would some one explain why? I have seen Child2 style more than the other one.

Bochen Lin
  • 413
  • 4
  • 12
  • 1
    "identical" is not well defined. Err, it's well-defined and they're not. But for all practical purposes, if `interface IB : IA`, there's no point to stating `class B : IB, IA` compared to just `class B : IB`. The only difference would be if someone later changed `IB` *not* to inherit from `IA`. Then that would *create* a difference. But not normally something to worry about at design time. Just implement `IParent` and be done with it. – Dax Fohl Aug 16 '17 at 05:30
  • 1
    If you're seeing Child2 style more often, then definitely inquire internally why. I don't see much of an advantage of that, but maybe someone there can clarify. If clarification doesn't make sense, then ask here again. But MS for example doesn't explicitly declare e.g. `List : IEnumerable` https://referencesource.microsoft.com/#mscorlib/system/collections/generic/list.cs – Dax Fohl Aug 16 '17 at 05:47
  • It is a stylistic choice, you only "should" if your team's coding standard dictates it. Implicit vs explicit implementation has nothing to do with it, both styles demand explicit if the interfaces have a member name in common. If you work without a coding standard at all and just have no preference then just do it the way the Microsoft programmer's do it, 2nd style. – Hans Passant Aug 16 '17 at 07:54
  • I personally prefer 1st style but then I see List in 2nd style which make me wondering if I have been doing the wrong thing. – Bochen Lin Aug 16 '17 at 22:31

2 Answers2

4

Implicit interface implementation takes place when there is no conflicting method names from diffirent interfaces, and it is the common case.
Excplicit, on the other hand, is when there are conflicting method names, and at this point you have to specify which interface implements in the method.

public interface IFoo
{
    void Do();   // conflicting name 1
}

public interface IBar
{
    void Do();   // conflicting name 2
}

public class FooBar : IFoo, IBar
{
    void IFoo.Do()    // explicit implementation 1
    {            
    }

    void IBar.Do()    // explicit implementation 1
    {
    }
}

Notice that excplicitly implemented interface methods cannot be public. Here you can read more about explicit interface implementation.

Talking about your specific example. You can safely use only IParent. Even if you would like to use excplicit interface implementation, you still can do it without specifically mentioning IGrandparent in class declaration.

interface IGrandparent
{
    void DoSomething();
}

interface IParent : IGrandparent
{
    void DoSomethingElse();

    void DoSomething();
}

public class Child : IParent
{
    void IGrandparent.DoSomething()
    {
    }

    public void DoSomethingElse()
    {
    }

    public void DoSomething()
    {
    }
}

EDIT: As Dennis pointed out, there are several other cases of explicit interface implementation usage, including interface re-implementation. I found very good reasoning for implicit vs explicit interface implementation usages in here (you may also want to check out the whole thread, it's fascinating).

Dmitry Volkov
  • 1,347
  • 1
  • 18
  • 33
  • "Excplicit... is when there are conflicting method names" - actually, this isn't the only case. At least, there are 2 more cases: 1) interface re-implementation, when base class maps interface method to non-virtual one; 2) when one wants to hide particular interface implementation to use it only with some special scenarios (e.g., see `IObjectContextAdapter` in EF6). – Dennis Aug 16 '17 at 06:33
1

They are identical.

This is not about explicit interface implementation, because one can implement interface explicitly using both Child1 and Child2 styles, e.g.:

public class Child2 : IGrandparent, IParent
{
    void IGrandparent.DoSomething()
    {
        throw new NotImplementedException();
    }

    public void DoSomethingElse()
    {
        throw new NotImplementedException();
    }
}

public class Child1 : IParent
{
    void IGrandparent.DoSomething()
    {
        throw new NotImplementedException();
    }

    public void DoSomethingElse()
    {
        throw new NotImplementedException();
    }
}

Note, that this shouldn't be confused with interface re-implementation within class hierarchy:

public class Child1 : IParent
{
    public void DoSomething()
    {
        Console.WriteLine("Child1.DoSomething");
    }

    public void DoSomethingElse()
    {
        Console.WriteLine("Child1.DoSomethingElse");
    }
}

public class Child2 : Child1, IGrandparent
{
    // Child2 re-implements IGrandparent
    // using explicit interface implementation
    void IGrandparent.DoSomething()
    {
        Console.WriteLine("Child2.DoSomething");
    }
}

I'd avoid Child2 style. It's just a visual trash. Moreover, if IGrandparent isn't your responsibility, then sometime you will get this:

interface IGrandparent : ICthulhu { ... }

Do you want to update your code this way:

public class Child2 : ICthulhu, IGrandparent, IParent { ... }

?

Dennis
  • 37,026
  • 10
  • 82
  • 150
  • I prefer Child1 style, but too many Child2 style make me worry and that is why I have this question. Thanks guys. – Bochen Lin Aug 16 '17 at 22:35