一切都从对象继承。这是继承的基础。一切都可以隐式地构建继承树,即。

object me = new Person();

因此,在这个逻辑结论之后,一群人也将成为一组对象:

List<Person> people = new List<Person>();
people.Add(me);
people.Add(you);
List<object> things = people; // Ooops.

除非,这不起作用,设计.NET的人要么忽略了这个,要么有理由,而且我不确定哪个。至少有一次我遇到了一个有用的情况,但我不得不最后使用一个讨厌的黑客(子类化List只是为了实现一个强制转换操作符)。

问题是:这种行为是否有原因?是否有更简单的解决方案来获得所需的行为?

为了记录,我相信我想要这种行为的情况是一个通用的打印功能,它通过调用ToString()并很好地格式化字符串来显示对象列表。

有帮助吗?

解决方案

好的,在.net中使用过泛型的每个人都必须在某个时刻碰到这个问题。

是的,直觉上它应该有效。不,在当前版本的C#编译器中它没有。

Eric Lippert对这个问题有一个非常好的解释(它有11个部分或者什么东西,会让你在某些地方弯曲,但是值得一读)。请参见此处

编辑:

挖出另一个相关链接,这个讨论java如何处理这个。请参见此处

其他提示

你可以使用linq来施展它:

IEnumerable<Person> oldList = someIenumarable;
IEnumerable<object> newList = oldlist.Cast<object>()
乍一看,这并不具有直观意义。但确实如此。看看这段代码:

List<Person> people = new List<Person>();
List<object> things = people; // this is not allowed
// ...
Mouse gerald = new Mouse();
things.add(gerald);

现在我们突然有一个ListPerson对象......里面有一个Mouse

这解释了为什么不允许将A<T>类型的对象赋值给类型为A<S>的变量,即使ST的超类型。

linq解决方案很好。由于您使用的是类型对象,另一种解决方法是将列表作为IEnumerable(而不是通用版本)传递。

编辑:C#4(目前为测试版)支持IEnumerable中的协变类型参数。虽然您无法直接分配给List <!> lt; object <!> gt;,但您可以将列表传递给期望IEnumerable <!> lt; object <!> gt;。

虽然您尝试做的事情确实在逻辑上流动,但它实际上是许多语言本身不支持的功能。这就是所谓的co / contra方差,它与何时以及如何通过编译器将对象从一个事物隐式地转换为另一个事物有关。值得庆幸的是,C#4.0将为C#竞技场带来协方差和逆转,这样的隐式演员应该是可能的。

有关详细说明,以下Channel9视频应该会有所帮助:

http://channel9.msdn.com/shows/Going+Deep/Inside-C-40-dynamic-type-optional-parameters-more-COM-friendly/

使用linq扩展方法,您可以

IEnumerable<object> things = people.Cast<object>();
List<object> things = people.Cast<object>().ToList();

否则,由于您强烈键入列表,因此不允许隐式转换。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top