C# 通用方法:如何使用可用的最专门的方法强制
我在接口C# 通用方法:如何使用可用的最专门的方法强制,c#,generics,interface,overloading,generic-method,C#,Generics,Interface,Overloading,Generic Method,我在接口IInterface中定义了一个通用方法Use。我试图实现该接口,其中Use方法的具体实现取决于实际类型T,我希望始终调用最专门的方法。但它不起作用: interface IInterface { void Use<T>(T other) where T : IInterface; } interface IChildInterface : IInterface { } class ImplementsIInterface : IInterface
IInterface
中定义了一个通用方法Use
。我试图实现该接口,其中Use
方法的具体实现取决于实际类型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)");
}
}
采用ichilInterface
参数的方法永远不会被调用,尽管它应该被调用
有什么办法可以让这一切顺利进行吗?还是我的方法根本错误?
请注意,IInterface
必须只有一个方法定义。我可以随时扩大接口层次结构(从而增加我可以在实现类中提供的实现的数量),但这不应该导致需要在IInterface
中添加更多的方法定义。否则,将错过使用接口的全部要点(即灵活)
到目前为止,我得到的答案都涉及到投球的需要。这也是我不想做的事情,因为这会使整个设置毫无用处。让我解释一下我试图实现的目标: 让我们想象一下,我们创建了一个
IInterface
的实例(比如:IInterface foo=new ImplementsChildInterface();
)。它将以某种方式运行,但它将始终以相同的方式运行-无论我们将其视为i接口
、i接口
或实现接口
。因为,如果我们对它调用某个方法,编译器(或运行时?我不知道)将检查它的实际类型,并运行在该类型中定义的方法
现在假设我们有两个i1
和i2
的IInterface
实例。它们同样是,IInterface
的具体实现,因此它们有一个具体的行为,不管我们从哪个角度看它们
因此,当我运行i1.Use(i2)
时,编译器(或运行时?)应该能够找出i1
和i2
的真正含义,并运行相应的方法。像这样:
i1
有哪种类型<代码>实现接口,好的,然后我来看看那里的方法i2
有哪种类型ImplementsIInterface
,好的,那么让我们看看是否存在一个方法Use(ImplementsIInterface…
)。没有,但也许有退路ImplementsIInterface
是一个IInterface
,所以让我们看看是否存在一个方法Use(IInterface…
)。是的,它是存在的,所以我们叫它李>
IInterface
和iChilInterface
均未定义成员Use(iChilInterface-other)
,但仅定义Use(T-other)
另一侧的类ImplementsChildInterface
有一个方法Use(IChildInterface other)
。当您将childInterf
声明为IChildInterface
类型的引用时,您不能访问该成员,但必须访问接口中定义的成员。因此,您应该强制转换到实际的类,以便访问接受iChilInterface
实例的方法。但即便如此,还是使用了通用实现。因此,您还应该将参数强制转换为iChilInterface
:
ImplementsChildInterfacechildinterf = new ImplementsChildInterface();
childinterf.Use(((IChildInterface)new ImplementsChildInterface());
childinterf.Use(new ImplementsIInterface());
void Use<T>(IChildInterface other) where T : IChildInterface;
此外,由于在更专门的方法中不使用泛型类型参数,因此也可以省略它:
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 childinterf = new ImplementsChildInterface();
childinterf.Use<IChildInterface>(new ImplementsChildInterface()); // outputs "ImplementsChildInterface.Use(IInterface)"
ichilInterface childInterface=new implementschilInterface();
childinterf.Use(新实现childinterface());//输出“实现接口.使用(接口)”
它将打印所需的输出。
childinterf.Use(((iChilInterface)new ImplementsChildInterface());
强制转换仍然不起作用。您是否也将childInterface
强制转换为实际类?您需要两者。或者,从其声明开始,让它成为该类型:ImplementsChildInterface=new ImplementsChildInterface();
。您使用术语“具体实现”和“专门化”就好像C语言泛型就像C++模板一样,它们不是很好。我不是说这是迂腐的,而是指出这些语言是如何达到超载分辨率的根本区别,如果你反对模型,你将遇到一段不愉快的时间。如果你想可靠地调用最具体的方法,请考虑VIR。实际方法,而不是泛型方法。@Jeroenmoster所说的“思考虚拟方法,而不是泛型方法”你的意思是完全不考虑接口吗?因为我考虑过更改iChilInterface
如下:interface iIchilInterface:IInterface{重写void Use(T other),其中T:iChilInterface;}
,但这种重写似乎是不可能的。至少在类中是可能的。我真的很感激你的提示,因为它清楚地表明我的方法是注定要失败的。但我想不出一个在C#中工作的替代对象模型。“哪种类型……有?”如果您想在运行时解决这些问题,您需要虚拟方法或反射(是
,是
)。泛型将不会帮助您,因为它们只查看它们所使用的上下文的编译时类型。ImplementsChildInterface.Use(IChildInterface other)
永远不能通过iChilInterface
调用,因为iChilInterface
没有该方法。您可以随意命名它,但由于签名不匹配,它不能作为接口的实现。只能使用(而不是其他)
can。为什么你的类中甚至有两个方法?为什么不使用一个接口和一个方法呢?你可以让use(T other)
执行运行时类型检查,或者使用双重分派,并给T
一个你调用的虚拟方法(但这假设
IChildInterface childinterf = new ImplementsChildInterface();
childinterf.Use<IChildInterface>(new ImplementsChildInterface()); // outputs "ImplementsChildInterface.Use(IInterface)"