c# - 为什么 List<T> 在协变接口(interface) MyInterface<out T> 上无效

标签 c# generics inheritance covariance type-inference

跟进问题 a previous question ,这已被确定为协方差问题。更进一步,如果我按如下方式修改 IFactory:

class Program
{
    static void Main(string[] args)
    {
        IFactory<IProduct> factory = new Factory();
    }
}

class Factory : IFactory<Product>
{
}

class Product : IProduct
{
}

interface IFactory<out T> where T : IProduct
{
    List<T> MakeStuff();
}

interface IProduct
{
}

我得到:

Invalid variance: The type parameter T must be invariantly valid on Sandbox.IFactory.MakeStuff(). T is covariant.

为什么这不是总是有效的?如何/应该如何解决?

最佳答案

其他答案是正确的,但解释为什么编译器将其标记为不安全是有指导意义的。假设我们允许它;会出什么问题?

class Sprocket: Product {}
class Gadget : Product {}
class GadgetFactory : IFactory<Gadget> 
{ 
    public List<Gadget> MakeStuff() 
    { 
        return new List<Gadget>() { new Gadget(); } 
    }
}
... later ...
IFactory<Gadget> gf = new GadgetFactory();
IFactory<Product> pf = gf; // Covariant!
List<Product> pl = pf.MakeStuff(); // Actually a list of gadgets
pl.Add(new Sprocket());

嘿,我们刚刚将链轮添加到只能包含小工具的列表中。

编译器只能在一个地方检测到问题,那就是在接口(interface)声明中。

对于有些过于特化的错误消息,我们深表歉意。我想不出更好的办法。

关于c# - 为什么 List<T> 在协变接口(interface) MyInterface<out T> 上无效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6390728/

相关文章:

c# - Unity C# Player 使用 Rigidbody2D.AddForce 速度太快

arrays - Swift 获取通用类型的数组

java - 所有子类(泛型?)的一种构建器方法实现

c# - 如何接受任何类型的泛型参数?

Java - 理解继承

c# - 继承方法无法访问派生类中的新实现

c# - 如何在C#中获取图像按钮ID?

c# - 完成构建后,Visual Studio 2015 卡住

c# - 关于任务编程的问题

C++子类参数化类,并将子类用作特化