[英]Generic Implementation of interface with specified type
我有一个有趣的情况,我想使用一个类类参数的基类来实现一个接口,并保持DRY继承类。
public interface ICalculator
{
void Process(ICalculationModel calculationModel);
}
public abstract class CalculatorBase<T> :ICalculator where T : ICalculationModel
{
// Compiler moans that Process(ICalculationModel calculationModel) isn't implemented
public abstract void Process(T calculationModel);
}
public class PipeworkInspections : CalculatorBase<GasSafetyModel>
{
public override void Process(GasSafetyModel documentModel){
//snip
}
}
通用的'where'条款或其他什么东西我缺少什么? 在我的脑海里,这应该工作。 或者编译器是否需要与接口定义完全相同的实现?
我不能轻易地将类型参数移动到ICalculator中,因为有很多地方使用它而不需要通用。
这已经解决了。 谢谢(你的)信息。 现在显然一个解决方案是使接口采用类型参数。 然而ICalculator的用法很多,并且被引用为ICalculator
我现在得到编译器错误,如果我省略了引用ICalculator的接口中的类型参数...有没有办法设计这应该工作!?
在我的脑海里,这应该工作。
问题就出在你的头上! :-)这不应该工作。 让我们看看为什么。
interface ICage
{
void Enclose(Animal animal);
}
class ZooCage<T> : ICage where T : Animal
{
public void Enclose(T t) { ... }
}
...
var giraffePaddock = new ZooCage<Giraffe>();
var cage = (ICage)giraffePaddock;
var tiger = new Tiger();
icage.Enclose(tiger);
现在长颈鹿围场里有一只老虎,生活对老虎有好处,但对长颈鹿来说却不好。 这就是为什么这是非法的。
或者编译器是否需要与接口定义完全相同的实现?
实现接口成员的成员必须与已实现方法的签名完全匹配。 例如,您不能使用返回类型协方差:
interface I
{
Animal GetAnimal();
}
class C : I
{
public Giraffe GetAnimal() { ... } // not legal.
}
合同要求动物; 你提供长颈鹿。 从逻辑上讲,这应该是有效的,但这在C#中是不合法的。 (它是在C ++中。)
请参阅本网站上有关返回类型协方差的任何问题,原因如下。
类似地,参数类型相反:
interface I
{
void PutMammal (Mammal mammal);
}
class C : I
{
public PutMammal(Animal animal) { ... } // not legal.
}
同样,这在逻辑上是合理的; 合同要求你带一个哺乳动物,这需要任何动物。 但同样,这不合法。
C#中有一些协变和逆变操作; 请参阅本网站上有关这些主题的众多问题,或浏览ericlippert.com或我之前的msdn博客上的协方差和逆变文章。
如果这样有效,那么你可以说出这样的话:
PipeworkInspections pipeworks = new PipeworkInspections();
ICalculator calculator = pipeworks;
NuclearPowerSafetyModel nuclearModel = new NuclearPowerSafetyModel();
calculator.Process(nuclearModel); // <-- Oops!
这可能不是你想要的......
你的界面说任何实现它的类都会提供这个方法:
void Process(ICalculationModel calculationModel);
现在显然PipeworkInspections
没有 。 它没有接受任何ICalculationModel
的方法Process
。 IT只有一个方法接受ICalculationModel
特定实现 。 所以你的编译失败了。
是的,您需要确切的实施。
作为替代方案,如果它适用于您,可以使interface
和Process
方法通用:
public interface ICalculator<T> where T : ICalculationModel
{
void Process(T calculationModel);
}
public abstract class CalculatorBase<T> : ICalculator where T : ICalculationModel
{
public abstract void Process(T calculationModel);
}
我同意Eric Lippert的回答:你做不到。 他以非常好的方式解释了为什么会这样。
如果你真的想这样做,你可以将以下内容添加到抽象类中,它将编译:
void ICalculator.Process(ICalculationModel calcMod)
{
Process((T)calcMod);
}
但您需要知道自己在做什么,否则在运行时可能会出现一些InvalidCastException
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.