【问题标题】:C# Generic Type InheritanceC# 泛型类型继承
【发布时间】:2013-10-08 22:25:10
【问题描述】:

我有一个接口,ICheese,我希望能够根据需要进行扩展。它包含在实现 IFruit 接口的类中:

public interface IFruit<T> where T : ICheese
{
    T : cheese { get; }
}

这样做是为了避免 C# 没有返回类型协变这一事实;我希望能够拥有 IFruit 的任何实现,并且知道它里面有一些 IChese 版本。

IFruit 与一些 ICrackers 交谈,他们提到了 IFruit:

public interface ICracker<T> where T : ICheese
{
    void Initialize(IFruit<T> fruit);
}

public abstract class Cracker<T> where T : ICheese
{
    IFruit<T> fruit        

    public void Initialize(IFruit<T> fruit)
    {
        this.fruit = fruit;
    }
}

只要 ICracker 的实现明确定义了它要使用的 IChese 类型,它就可以工作:

public class Apple : IFruit<Cheddar> {/* Implementation of Class */}

public class Saltine : Cracker<Cheddar> {/* Implementation of Class */}

在这种情况下,在 Saltine 实例上调用 Initialize(new Apple()) 有效。

但是,如果我们有这样的 ICracker:

public class Ritz : Cracker<ICheese> { /* Implementation of Class */ }

我无法将 Apple 传递给 Rizt 的 Initialize() 函数,即使 Cheddar 继承自 ICheese。有没有一种方法可以让这个工作或可以实现相同目标的模式?基本想法是,我希望 ICrackers 能够说“我至少需要这个版本的 ICheese”,并且能够接受任何至少提供那个版本的 ICheese 的 IFruit。

【问题讨论】:

    标签: c# generics inheritance covariance


    【解决方案1】:

    您可以使IFruitT 中协变:

    public interface IFruit<out T> where T : ICheese
    {
        T Cheese { get; }
    }
    

    【讨论】:

    • 当我这样做时,我不能使用“set”。有没有办法解决这个问题?
    • @TaylorHadden - 您不能向Cheese 属性添加setter 并保留IFruit 的协方差,因为它不安全。我假设您的示例已简化,因此如果没有看到 Cracker&lt;T&gt;.Initialize 的实现,很难说出您还能做什么。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-27
    • 2015-09-15
    • 2011-05-01
    • 1970-01-01
    • 2021-10-11
    • 2018-08-01
    相关资源
    最近更新 更多