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

Mat*_*att 12 .net c# interface explicit-implementation

举个例子:

public interface IFoo
{
    IFoo Bar();
}

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

    IFoo IFoo.Bar() { return Bar(); } //Why is this necessary?
}
Run Code Online (Sandbox Code Playgroud)

为什么IFoo Bar()即使Foo转换为IFoo没有强制转换,隐式实现也是必要的?

Aar*_*ver 5

微软已经详细介绍了这个主题,但它归结为多个接口/类的实现,它们具有相同的方法.隐含不再适用于该上下文.

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
Run Code Online (Sandbox Code Playgroud)

如果我们采取明确的方法,我们最终会得到这个.

public class SampleClass : IControl, ISurface
{
    void IControl.Paint()
    {
        System.Console.WriteLine("IControl.Paint");
    }
    void ISurface.Paint()
    {
        System.Console.WriteLine("ISurface.Paint");
    }
}
Run Code Online (Sandbox Code Playgroud)

这一切都归结为在实现的类型冲突时提供唯一性.在你的例子中,Foo 是 IFoo.


Lee*_*Lee 5

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

public Foo Bar()
{
    //...
}
Run Code Online (Sandbox Code Playgroud)

IFoo由于方法的返回类型Bar不同,因此不满足接口.

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

  • @IlyaKogan - 我不知道为什么C#不支持返回型协方差 - 你必须问设计师.C#通常更喜欢事物是明确的,因此可能会阻止接口被隐式地意外实现. (2认同)

Ily*_*gan 4

你可以这样解决它(有点难看,但可以处理强类型):

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

public class Foo : IFoo<Foo>
{
    public Foo Bar()
    {
        //...
    }
}
Run Code Online (Sandbox Code Playgroud)