[英]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.