C# 我应该包括继承链中的所有接口吗?

C# 我应该包括继承链中的所有接口吗?,c#,inheritance,interface,C#,Inheritance,Interface,如果我有两个接口: interface IGrandparent { void DoSomething(); } interface IParent : IGrandparent { void DoSomethingElse(); } 然后有两种实现: //only includes last interface from the inheritance chain public class Child1 : I

如果我有两个接口:

    interface IGrandparent
    {
        void DoSomething();
    }

    interface IParent : IGrandparent
    {
        void DoSomethingElse();
    }
然后有两种实现:

//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();
    }
}

这两种实现相同吗?(除了类名)?有人说这与“隐式和显式实现”有关,有人能解释为什么吗?我见过的Child2样式比另一种样式更多。

隐式接口实现发生在不同接口没有冲突的方法名称时,这是常见的情况。
另一方面,Excplicit是当存在冲突的方法名称时,此时必须指定在方法中实现的接口

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
    {
    }
}
请注意,免责实现的接口方法不能是公共的。

谈谈你的具体例子。您只能安全地使用
iPart
。即使您希望使用excplicit接口实现,也可以在类声明中不特别提到
IGrandparent

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:如前所述,还有其他几种显式接口实现用法,包括接口重新实现。我在中找到了隐式与显式接口实现用法的很好的理由(您可能还想查看整个线程,这很有趣)。

它们是相同的

这与显式接口实现无关,因为可以使用
Child1
Child2
样式显式实现接口,例如:

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();
    }
}
请注意,这不应与类层次结构中的接口重新实现混淆:

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");
    }
}
我会避免孩子2的风格。这只是一个视觉垃圾。此外,如果您不负责
IGrandparent
,那么有时您会得到:

interface IGrandparent : ICthulhu { ... }
是否要按以下方式更新代码:

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

“相同”的定义不明确。呃,这是定义明确的,但事实并非如此。但就所有实际目的而言,如果
接口IB:IA
,那么与仅
类B:IB
相比,说明
类B:IB,IA
是没有意义的。唯一的区别是,如果后来有人更改了
IB
而不是从
IA
继承。那么这将产生不同。但在设计时通常不需要担心。只需实现IParent,并完成它。如果您更经常看到Child2样式,那么一定要在内部询问原因。我看不出这有什么好处,但也许有人可以澄清一下。如果澄清没有意义,请在这里再次询问。但MS没有明确声明,例如:IEnumerable这是一种风格选择,只有在团队的编码标准规定的情况下,您才“应该”。隐式和显式实现与此无关,如果接口有共同的成员名称,则这两种样式都要求显式。如果你的工作完全没有编码标准,只是没有偏好,那么就按照微软程序员的方式来做,第二种风格。我个人更喜欢第一种风格,但后来我看到第二种风格的列表,这让我怀疑我是否做了错事。“Excplicit…是指方法名称冲突”-实际上,这不是唯一的情况。至少还有两种情况:1)当基类将接口方法映射到非虚拟方法时,接口重新实现;2) 当人们想隐藏特定的接口实现以仅在某些特殊场景下使用它时(例如,请参见EF6中的
IObjectContextAdapter
),我更喜欢Child1样式,但太多的Child2样式会让我担心,这就是为什么我有这个问题。谢谢各位。