泛型方法:如何强制使用最专业的方法

时间:2017-09-08 10:25:22

标签: c# generics interface overloading generic-method

我在接口Use<T>中定义了一个通用方法IInterface。我尝试创建该接口的实现,其中Use<T>方法的具体实现取决于实际类型T,并且我希望始终调用最专业的方法。但它不起作用:

    interface IInterface { void Use<T>(T other) where T : IInterface; }
    interface IChildInterface : IInterface { }
    class ImplementsIInterface : IInterface
    {
        public void Use<T>(T other) where T : IInterface
        {
            Debug.WriteLine("ImplementsInterface.Use(IInterface)");
        }
    }
    class ImplementsChildInterface : IChildInterface
    {
        public void Use<T>(IChildInterface other) where T : IInterface
        { // idea: if other is IChildInterface, use this method
            Debug.WriteLine("ImplementsChildInterface.Use(IChildInterface)");
        }

        public void Use<T>(T other) where T : IInterface
        { // idea: if above method is not applicable, use this method
            Debug.WriteLine("ImplementsChildInterface.Use(IInterface)");
        }
    }

这是我的主要方法:

    public static void Main()
    {
        IChildInterface childinterf = new ImplementsChildInterface();

        childinterf.Use(new ImplementsChildInterface()); // outputs "ImplementsChildInterface.Use(IInterface)"
                                                         // but should output "ImplementsChildInterface.Use(IChildInterface)"

        childinterf.Use(new ImplementsIInterface());     // outputs "ImplementsChildInterface.Use(IInterface)"
    }

从不调用带有IChildInterface参数的方法,尽管它应该。

有没有办法让这项工作?或者我的方法根本错误?

请注意,IInterface只需要一个方法定义。我可以随时扩大接口层次结构(从而增加我可以在实现类中提供的实现数量),但这不应该导致需要在IInterface中添加更多方法定义。否则,将错过使用界面的整个要点(即灵活)。

到目前为止我得到的答案都涉及到施放的必要性。这也是我不想做的事情,因为它使整个设置无用。让我解释一下我试图实现的更广泛的情况:

让我们假设我们创建了一个IInterface的实例(如此:IInterface foo = new ImplementsChildInterface();)。它将以某种方式运行,但它始终以相同的方式运行 - 无论我们将其视为IInterfaceIChildInterface还是ImplementsChildInterface。因为,如果我们在其上调用某个方法,编译器(或运行时?我不知道)将检查它真正的类型并运行该类型中定义的方法。

现在假设我们有两个i1i2 IInterface的实例。它们又是IInterface的具体实现,所以它们具有一种具体的行为,无论我们看起来是哪种眼镜。

因此,当我运行i1.Use(i2)时,编译器(或运行时?)应该能够找出i1i2真正的内容,并运行相应的方法。像这样:

  1. i1有哪种类型? ImplementsChildInterface,好的,然后我会看看那里的方法。
  2. i2有哪种类型? ImplementsIInterface,好的,然后让我们看看是否存在方法Use(ImplementsIInterface ...)。没有,但也许有一个后备? ImplementsIInterfaceIInterface,所以让我们看看是否存在方法Use(IInterface ...)。是的,它存在,所以我们称之为!

1 个答案:

答案 0 :(得分:2)

IInterfaceIChildInterface都没有定义成员Use<T>(IChildInterface other),只有Use<T>(T other)

另一方的您的课程ImplementsChildInterfaceUse<T>(IChildInterface other)方法。当您将childInterf声明为类型IChildInterface的引用时,您无法访问该成员,但不能访问界面中定义的成员。因此,您应该转换为实际的类,以便访问接受IChildInterface实例的方法。但即使这样,也使用了通用实现。因此,您还应将参数转换为IchildInterface

ImplementsChildInterfacechildinterf = new ImplementsChildInterface();
childinterf.Use(((IChildInterface)new ImplementsChildInterface()); 
childinterf.Use(new ImplementsIInterface());

此外,由于您没有在更专业的方法中使用泛型类型参数,因此您也可以省略它:

class ImplementsChildInterface : IChildInterface
{
    public void Use(IChildInterface other)
    { // idea: if other is IChildInterface, use this method
        Debug.WriteLine("ImplementsChildInterface.Use(IChildInterface)");
    }

    public void Use<T>(T other) where T : IInterface
    { // idea: if above method is not applicable, use this method
        Debug.WriteLine("ImplementsChildInterface.Use(IInterface)");
    }
}

另外,您也可以在IChildInterface

中添加方法
void Use<T>(IChildInterface other) where T : IChildInterface;

现在你可以使用

IChildInterface childinterf = new ImplementsChildInterface();
childinterf.Use<IChildInterface>(new ImplementsChildInterface()); // outputs "ImplementsChildInterface.Use(IInterface)"

将打印所需的输出。