在C#中,为什么接口实现必须明确地实现另一个方法版本?

时间:2012-12-19 19:42:23

标签: c# .net interface explicit-implementation

举个例子:

public interface IFoo
{
    IFoo Bar();
}

public class Foo : IFoo
{
    public Foo Bar()
    {
        //...
    }

    IFoo IFoo.Bar() { return Bar(); } //Why is this necessary?
}

为什么IFoo Bar()的隐式实现是必要的,即使Foo在没有演员的情况下转换为IFoo

5 个答案:

答案 0 :(得分:5)

微软在这个主题上有一个detailed write up,但它归结为多个接口/类的实现,它们具有相同的方法。 在该上下文中隐含不再有效

class Test 
{
    static void Main()
    {
        SampleClass sc = new SampleClass();
        IControl ctrl = (IControl)sc;
        ISurface srfc = (ISurface)sc;

        // The following lines all call the same method.
        sc.Paint();
        ctrl.Paint();
        srfc.Paint();
    }
}


interface IControl
{
    void Paint();
}
interface ISurface
{
    void Paint();
}
class SampleClass : IControl, ISurface
{
    // Both ISurface.Paint and IControl.Paint call this method.  
    public void Paint()
    {
        Console.WriteLine("Paint method in SampleClass");
    }
}

// Output: 
// Paint method in SampleClass 
// Paint method in SampleClass 
// Paint method in SampleClass

如果我们采取明确的方法,我们最终会这样做。

public class SampleClass : IControl, ISurface
{
    void IControl.Paint()
    {
        System.Console.WriteLine("IControl.Paint");
    }
    void ISurface.Paint()
    {
        System.Console.WriteLine("ISurface.Paint");
    }
}

这一切都归结为在实现的类型冲突时提供唯一性。在您的示例中,Foo IFoo

答案 1 :(得分:5)

在这种情况下需要它,因为C#不支持接口的返回类型协方差,所以你的函数

public Foo Bar()
{
    //...
}

不满足IFoo接口,因为Bar方法的返回类型不同。

由于您还希望实现该接口,因此您必须明确这样做,因为您已经在类上定义了Bar()方法。

答案 2 :(得分:4)

你可以像这样解决它(有点难看,但要注意强打字):

public interface IFoo<T> where T : IFoo<T>
{
    T Bar();
}

public class Foo : IFoo<Foo>
{
    public Foo Bar()
    {
        //...
    }
}

答案 3 :(得分:3)

因为您可能并不总是希望实现接口的方法的行为与具有相同签名的方法的另一个版本的行为相同。

您可能还希望一个类为接口实现一个方法,但是该方法不能从类本身的实例访问。

答案 4 :(得分:0)

我建议您将隐式实现保留为受保护而不是公共。

public class Foo : IFoo
{
    **protected virtual** Foo Bar()
    {
        //...
    }

    IFoo IFoo.Bar() { return Bar(); } 
}

对于为什么/何时在此线程中使用显式实现,有一个非常广泛的答案:

implicit vs explicit interface implementation

使用显式实现的一个很好的理由是,当您使用Foo类时,可以轻松地使用依赖注入来获得更松散的耦合。