Fir*_*oso 9 c# generics inheritance type-inference covariance
跟进前一个问题的问题,这被认为是一个共同变异问题.更进一步,如果我修改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
{
}
Run Code Online (Sandbox Code Playgroud)
我明白了:
方差无效:类型参数T必须在Sandbox.IFactory.MakeStuff()上无效.T是协变的.
为什么这不是无效的?如何/应该如何解决?
Eri*_*ert 12
其他答案是正确的,但有理由说明为什么编译器将此标记为不安全.假设我们允许它; 什么可能出错?
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());
Run Code Online (Sandbox Code Playgroud)
嘿,我们刚刚将一个链轮添加到一个只能包含小工具的列表中.
只有一个地方,编译器可以检测到问题,这是在接口的声明中.
对于有点过于乐观的错误消息感到抱歉.我无法想出更好的东西.
@Craig的回答是正确的.要解决,请将其更改为:
IEnumerable<T> MakeStuff()
Run Code Online (Sandbox Code Playgroud)
编辑:至于原因,请看IEnumerable <T>接口的定义:
public interface IEnumerable<out T> : IEnumerable
Run Code Online (Sandbox Code Playgroud)
请注意,IList <T>接口没有out关键字.接口和委托中的泛型类型参数支持差异,而不支持类,因此它不适用于List <T>.
因为您可以在a中添加和删除对象List<T>
,所以T
必须始终是不变的,即使列表是函数结果也是如此.执行var l = MakeStuff()
完毕后,您可以将内容放入列表中或将其取出,因此T
必须保持不变.
归档时间: |
|
查看次数: |
1248 次 |
最近记录: |