C# 泛型集合冲突
这是我最好的尝试来重现这种情况C# 泛型集合冲突,c#,generics,covariance,C#,Generics,Covariance,这是我最好的尝试来重现这种情况 public interface IFoo { } public class Foo : IFoo { } public class Bar : IFoo { } public class CollectionOf<T> : List<IFoo> { } public class Bars : CollectionOf<Bar> { } public class Test { public void Te
public interface IFoo
{
}
public class Foo : IFoo { }
public class Bar : IFoo { }
public class CollectionOf<T> : List<IFoo>
{
}
public class Bars : CollectionOf<Bar>
{
}
public class Test
{
public void Test()
{
CollectionOf<IFoo> bars = new Bars();
}
}
公共接口IFoo
{
}
公共类Foo:IFoo{}
公共类栏:IFoo{}
公共类集合:列表
{
}
公共类酒吧:收藏
{
}
公开课考试
{
公开无效测试()
{
钢筋收集=新钢筋();
}
}
编译器抱怨实例化。Bars是Ifoo的集合。这是协方差/反方差问题之一吗?是的
如果允许这样做,您就可以将任何对象放入该集合中,只要它实现了IFoo
接口,但这对集合来说并不安全
让我举例说明:
var b = new Bars();
CollectionOf<IFoo> bars = b;
bars.Add(Dummy); // implements IFoo, but does not descend from Bar
var b=新条();
棒的收集=b;
条。添加(虚拟);//实现IFoo,但不从Bar下降
此时,b
包含什么?类型为虚拟的对象
?那将是不好的,因此这首先是不允许的。是的
想一想<代码>条应该能够合法地容纳实现IFoo
的任何类型的对象。但是,Bar
类型的对象只能容纳Bar
类型的对象
使用您的代码这是允许的,这显然是错误的
CollectionOf<IFoo> bars = new Bars();
bars.Add( new Foo() ); // Uh oh!
CollectionOf bar=新条();
添加(新的Foo());//哦!
这将有效地破坏通过泛型提供给您的类型安全性。如果有,修复将取决于什么不适合您。我可以用两种方式编译您的示例,要么使用IEnumerable,要么将CollectionOf定义为带有out泛型修饰符的接口。我不知道这两种方法是否适合你:
public interface IFoo { }
public class Foo : IFoo { }
public class Bar : IFoo { }
public interface CollectionOf<out T> : IEnumerable<IFoo> { }
public class Bars : CollectionOf<Bar> { }
public class Test
{
public void Test()
{
IEnumerable<IFoo> bars1 = new Bars();
CollectionOf<IFoo> bars2 = new Bars();
}
}
公共接口IFoo{}
公共类Foo:IFoo{}
公共类栏:IFoo{}
公共接口集合:IEnumerable{}
公共类栏:集合{}
公开课考试
{
公开无效测试()
{
IEnumerable条1=新条();
棒材2的收集=新棒材();
}
}
谢谢@EdS。解决方法是什么?如果您希望支持协方差/逆变,我们需要知道CollectionOf
是用于从集合中读取还是添加到集合中?它不能同时支持协方差和逆变。如果我承诺只在那个集合中放条会怎么样?这不是or的全部内容吗?如果您只想在集合中放置Bar
,为什么不使用CollectionOf Bar=new Bar()代码>?@Matthew:不,他们不允许有不正确的行为。除非您仅通过界面工作,否则您永远无法将Foo
添加到条的集合中。这不是C++;泛型是强类型的。这种情况将确保形成你的例子,这将导致行为没有意义,也没有在标准中定义。谢谢你,是的,这是完美的,因为。在哪里玩?
或协方差意味着类Foo
可以对其元素进行升级。例如,foomyfoo=newfoo()代码>。在这种情况下,T
只能用于返回类型(因此为out)。要了解更多信息,请查看这个,我相信这就是我要寻找的。我需要从CollectionOf中删除,所以out是我所需要的。