逻辑及其对Collections.Generic和继承的应用
-
02-07-2019 - |
题
一切都从对象继承。这是继承的基础。一切都可以隐式地构建继承树,即。
object me = new Person();
因此,在这个逻辑结论之后,一群人也将成为一组对象:
List<Person> people = new List<Person>();
people.Add(me);
people.Add(you);
List<object> things = people; // Ooops.
除非,这不起作用,设计.NET的人要么忽略了这个,要么有理由,而且我不确定哪个。至少有一次我遇到了一个有用的情况,但我不得不最后使用一个讨厌的黑客(子类化List只是为了实现一个强制转换操作符)。
问题是:这种行为是否有原因?是否有更简单的解决方案来获得所需的行为?
为了记录,我相信我想要这种行为的情况是一个通用的打印功能,它通过调用ToString()并很好地格式化字符串来显示对象列表。
其他提示
你可以使用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);
现在我们突然有一个List
的Person
对象......里面有一个Mouse
!
这解释了为什么不允许将A<T>
类型的对象赋值给类型为A<S>
的变量,即使S
是T
的超类型。
linq解决方案很好。由于您使用的是类型对象,另一种解决方法是将列表作为IEnumerable(而不是通用版本)传递。
编辑:C#4(目前为测试版)支持IEnumerable中的协变类型参数。虽然您无法直接分配给List <!> lt; object <!> gt;,但您可以将列表传递给期望IEnumerable <!> lt; object <!> gt;。的方法。 p>
虽然您尝试做的事情确实在逻辑上流动,但它实际上是许多语言本身不支持的功能。这就是所谓的co / contra方差,它与何时以及如何通过编译器将对象从一个事物隐式地转换为另一个事物有关。值得庆幸的是,C#4.0将为C#竞技场带来协方差和逆转,这样的隐式演员应该是可能的。
有关详细说明,以下Channel9视频应该会有所帮助:
使用linq扩展方法,您可以
IEnumerable<object> things = people.Cast<object>();
List<object> things = people.Cast<object>().ToList();
否则,由于您强烈键入列表,因此不允许隐式转换。