简体   繁体   中英

Multiple inheritance from the same interface in C#

Please consider the following program:

using System;

public interface IFoo
{
    void DoFoo();
}

public class Bar: IFoo
{
    public void DoFoo() => Console.WriteLine("BAR!");
}

public class Baz: Bar, IFoo
{
    void IFoo.DoFoo() => Console.WriteLine("baz!");
}

class Program
{
  static void Main()
  {
    Baz baz = new Baz();
    baz.DoFoo();
    
    IFoo foo = baz;
    foo.DoFoo();
    
    Bar bar = baz;
    bar.DoFoo();
    
    IFoo foobar = bar;
    foobar.DoFoo();
  }
}

It gives the following output which I personally with my C++ background consider highly unexpected:

BAR!
baz!
BAR!
baz!

Having , IFoo in the declaration of Baz seems to be substantial, because otherwise void IFoo.DoFoo() doesn't compile.

Can someone please explain what is going on here (especially the last line)? And what should be done to prevent such behavior in real life? Should one avoid implementing from the same interface at all or there are some other rules to avoid problems?

This is a difference in the explicit implementation ( void IFoo.DoFoo() ) vs the implicit implementation ( public void DoFoo() ). The compiler will use the explicit implementation first. If you provide both an explicit and implicit implementation then the difference becomes clear:

https://dotnetfiddle.net/7l9gIs


using System;

public interface IFoo
{
    void DoFoo();
}

public class Bar: IFoo
{
    public void DoFoo(){ Console.WriteLine("BAR!"); }
}

public class Baz: Bar, IFoo
{
    void IFoo.DoFoo(){ Console.WriteLine("baz explicit!"); }
    public new void DoFoo(){ Console.WriteLine("baz implicit!"); }
}

public class Program
{
  public static void Main()
  {
    Baz baz = new Baz();
    baz.DoFoo();
    
    IFoo foo = baz;
    foo.DoFoo();
    
    Bar bar = baz;
    bar.DoFoo();
    
    IFoo foobar = bar;
    foobar.DoFoo();
  }
}

Output

baz implicit!
baz explicit!
BAR!
baz explicit!

Implicit implementations tend to be more common and more convenient for usage. They are less verbose and any usage of the concrete type will have the implementations of the members exposed. Implicit implementations don't include the name of the interface being implemented before the member name, so the compiler infers this. The members will be exposed as public and will be accessible when the object is cast as the concrete type.

Visit this link for more details https://www.pluralsight.com/guides/distinguish-explicit-and-implicit-interface-implementation-csharp

The confusion is starting when you implement Baz from IFoo. Because Bar is already implements IFoo and Baz is the subclass of Bar. So, you dont need to do that.

In object oriented programming its not a best practice, in fact it is worst practice.

If you want to override DoFoo method, use the following code

public interface IFoo
{
    void DoFoo();
}

public class Bar : IFoo
{
    public virtual void DoFoo()
    {
        // do something
    }
}

public class Baz : Bar
{
    public override void DoFoo()
    {
        // override what you did in Bar class
    }
}

In your code, when you try to baz.DoFoo, in fact you are calling bar.DoFoo.Because you didnt override it. Its the problem.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM