3

一切都继承自对象。这是继承的基础。一切都可以隐式地投射到继承树上,即。

object me = new Person();

因此,按照其逻辑结论,一组人也将是一组对象:

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

除了那行不通,设计 .NET 的人要么忽略了这一点,要么是有原因的,我不确定是哪一个。至少有一次我遇到了这很有用的情况,但我最终不得不使用一个讨厌的 hack(子类化 List 只是为了实现一个强制转换运算符)。

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

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

4

6 回答 6

5

好的,每个在 .net 中使用过泛型的人一定都曾遇到过这种情况。

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

Eric Lippert 对这个问题有一个非常好的解释(它分为 11 部分或其他内容,会让你在某些地方弯曲,但它非常值得一读)。见这里

编辑:

挖出了另一个相关的链接,这个链接讨论了java如何处理这个。看这里

于 2008-09-21T03:13:30.957 回答
4

你可以使用 linq 来投射它:

IEnumerable<Person> oldList = someIenumarable;
IEnumerable<object> newList = oldlist.Cast<object>()
于 2008-09-21T03:13:11.550 回答
3

乍一看,这并没有直观的意义。但确实如此。看看这段代码:

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

现在我们突然有了一个List对象Person......Mouse里面有一个!

这解释了为什么不允许A<T>将类型对象分配给类型变量A<S>,即使它S是 的超类型T

于 2008-09-21T03:23:14.897 回答
3

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

编辑:C# 4(当前为 beta)支持 IEnumerable 中的协变类型参数。虽然您无法直接分配给 List<object>,但您可以将列表传递给需要 IEnumerable<object> 的方法。

于 2008-09-21T03:26:02.860 回答
2

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

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

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

于 2009-06-01T19:30:49.657 回答
1

使用 linq 扩展方法,您可以做到

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

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

于 2008-09-21T03:13:37.430 回答