c# - 接口(interface)实现两次 "types may unify";为什么此解决方法有效?

标签 c# inheritance interface-implementation

我在尝试为同一个类实现接口(interface)两次时遇到编译器错误,如下所示:

public class Mapper<T1, T2> : IMapper<T1, T2>, IMapper<T2, T1>
{
   /* implementation for IMapper<T1, T2> here.  */

   /* implementation for IMapper<T2, T1> here.  */
}

错误:

'Mapper' cannot implement both 'IMapper' and 'IMapper' because they may unify for some type parameter substitutions.

为什么这个解决方法有效?我想知道我是已经解决了问题还是只是欺骗了编译器。

public class Mapper<T1, T2> : MapperBase<T1, T2>, IMapper<T1, T2>
{
    /* implementation for IMapper<T1, T2> here. */
}

public class MapperBase<T1, T2> : IMapper<T2, T1>
{
    /* implementation for IMapper<T2, T1> here. */
}

编辑:我已将 MyClassMyClassBaseIMyInterface 更新为 MapperMapperBaseIMapper 来表示更真实的场景,在该场景中可能会出现此问题。

最佳答案

考虑这个实现:

public class MyClass<T1, T2> : IMyInterface<T1, T2>, IMyInterface<T2, T1>
{
   /* implementation for IMyInterface<T1, T2> here.  */

   /* implementation for IMyInterface<T2, T1> here.  */
}

什么是MyClass<int, int>实现?它实现了 IMyInterface<int, int>两次,因为 IMyInterface<T1, T2>IMyInterface<T2, T1>统一时 T1T2是平等的。这就是为什么同时实现 IMyInterface<T1, T2> 的原因和 IMyInterface<T2, T1>在同一个类(class)是不允许的。如果您尝试实现,例如 IMyInterface<int, T1>,同样的推理也适用。和 IMyInterface<T2, double> : 类型表达式统一为 T1 = double, T2 = int .

考虑这个实现:

public class MyClass<T1, T2> : MyClassBase<T1, T2>, IMyInterface<T1, T2>
{
    /* implementation for IMyInterface<T1, T2> here. */
}

public class MyClassBase<T1, T2> : IMyInterface<T2, T1>
{
    /* implementation for IMyInterface<T2, T1> here. */
}

您所做的是优先考虑 IMyInterface<T1, T2>IMyInterface<T2, T1> .如果T1T2是相等的,你有一个 MyClass<T1, T2> 的实例, IMyInterface<T1, T2>实现将被选中。如果你有一个 MyBaseClass<T1, T2> 的实例, IMyInterface<T2, T1>将选择实现。

这是一个向您展示行为的玩具程序。特别注意 a_as_i.M(0, 1) 的行为和 a_as_b.M(0, 1) .如果你要实现 I<T2, T1>明确在 B<T1, T2> (通过在方法名称前加上 I<T2, T1>. 前缀),将无法使用编译时语法调用它。反射(reflection)是必要的。

interface I<T1, T2>
{
    void M(T1 x, T2 y);
}

class A<T1, T2> : B<T1, T2>, I<T1, T2>
{
    public void M(T1 x, T2 y)
    {
        Console.WriteLine("A: M({0}, {1})", x, y);
    }
}

class B<T1, T2> : I<T2, T1>
{
    public void M(T2 x, T1 y)
    {
        Console.WriteLine("B: M({0}, {1})", x, y);
    }
}

class Program
{
    static void Main(string[] args)
    {
        //Outputs "A: M(0, 1)"
        var a = new A<int, int>();
        a.M(0, 1);

        //Outputs "B: M(0, 1)"
        var b = new B<int, int>();
        b.M(0, 1);

        //Outputs "A: M(0, 1)" because I<T1, T2>
        //takes precedence over I<T2, T1>
        var a_as_i = a as I<int, int>;
        a_as_i.M(0, 1);

        //Outputs "B: M(0, 1)" despite being called on an instance of A
        var a_as_b = a as B<int, int>;
        a_as_b.M(0, 1);

        Console.ReadLine();
    }
}

关于c# - 接口(interface)实现两次 "types may unify";为什么此解决方法有效?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22721763/

相关文章:

c# - reCaptcha 和 SSL 网站

java - 函数调用自身但不循环

java - 如何将 ArrayList 传递给以集合作为输入的方法

java - 为什么需要抽象方法?

c# - 在 C# 中,是否可以像在 VB.NET 中那样使用具有不同名称的成员来实现接口(interface)成员?

entity-framework - 为什么 DbContext 实现了 IObjectContextAdapter 但没有公共(public) ObjectContext 属性

c# - SQL BULK INSERT 的替代方案

c# - 如何在自定义 WebViewPage 中设置属性?

c# - 驱动程序可执行文件的路径必须由 webdriver.chrome.driver 系统属性设置 - Selenium 错误

c++ - 继承类的指针问题