簡體   English   中英

具有指定類型的接口的通用實現

[英]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 特定實現 所以你的編譯失敗了。

是的,您需要確切的實施。

作為替代方案,如果它適用於您,可以使interfaceProcess方法通用:

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM