跟进问题 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/