在C#中,为什么List <string>对象不能存储在List <object>variables中

看来List对象不能存储在C#中的Listvariables中,甚至不能以这种方式显式地转换。

List<string> sl = new List<string>(); List<object> ol; ol = sl; 

结果不能将typesSystem.Collections.Generic.List<string>隐式转换为System.Collections.Generic.List<object>

接着…

 List<string> sl = new List<string>(); List<object> ol; ol = (List<object>)sl; 

结果无法将typesSystem.Collections.Generic.List<string>转换为System.Collections.Generic.List<object>

当然,你可以把所有的东西都从string列表中拉出来放回去,但这是一个相当复杂的解决scheme。

想想这样,如果你要做这样的转换,然后将一个Footypes的对象添加到列表中,则string列表不再一致。 如果您要迭代第一个引用,则会得到类转换exception,因为一旦您点击Foo实例,Foo就无法转换为string!

作为一个方面说明,我认为你是否可以做反向演员会更有意义:

 List<object> ol = new List<object>(); List<string> sl; sl = (List<string>)ol; 

我有一段时间没有使用C#,所以我不知道这是否合法,但是这种types的转换实际上是(可能)有用的。 在这种情况下,你将从一个更普通的类(对象)转向更具体的类(string),从一般类inheritance。 这样,如果添加到string列表中,则不违反对象列表。

有人知道或可以testing,如果这样的演员在C#合法吗?

如果您使用.NET 3.5,请查看Enumerable.Cast方法。 这是一个扩展方法,所以你可以直接在列表中调用它。

 List<string> sl = new List<string>(); IEnumerable<object> ol; ol = sl.Cast<object>(); 

这不完全是你要求的,但应该做的伎俩。

编辑:如Zooba所指出的,你可以调用ol.ToList()来获得一个List

您不能在具有不同types参数的genericstypes之间进行转换。 专门的genericstypes不构成同一inheritance树的一部分,因此是不相关的types。

要做到这一点,NET-NET 3.5:

 List<string> sl = new List<string>(); // Add strings to sl List<object> ol = new List<object>(); foreach(string s in sl) { ol.Add((object)s); // The cast is performed implicitly even if omitted } 

使用Linq:

 var sl = new List<string>(); // Add strings to sl var ol = new List<object>(sl.Cast<object>()); // OR var ol = sl.Cast<object>().ToList(); // OR (note that the cast to object here is required) var ol = sl.Select(s => (object)s).ToList(); 

原因在于像List<>这样的generics类在大多数情况下被作为一个普通的类来处理。 例如当你说List<string>() ,编译器会说ListString() (它包含string)。 [技术人员:这是一个非常简单的英语版本]

因此,显然编译器不能够通过强制转换其内部集合的项目来将ListString转换为ListObject。

这就是为什么像Convert()这样的IEnumerable的扩展方法,它允许您轻松地为存储在集合中的项目提供转换,这可以像从一个铸造到另一个一样简单。

这与协方差有很大关系,例如,generics被视为参数,如果参数不能正确parsing为更具体的types,则操作失败。 这样的含义是,你不能像对象那样投射到一个更普通的types。 正如雷克斯所说,List对象不会为你转换每个对象。

你可能想尝试一下ff代码:

 List<string> sl = new List<string>(); //populate sl List<object> ol = new List<object>(sl); 

要么:

 List<object> ol = new List<object>(); ol.AddRange(sl); 

ol(理论上)将sl的所有内容都没有问题地复制。

是的,你可以从.NET 3.5:

 List<string> sl = new List<string>(); List<object> ol = sl.Cast<object>().ToList(); 

迈克 – 我相信在C#中反对也是不允许的

有关更多信息,请参阅CLR中的genericstypes参数差异 。

这实际上是因为你不会尝试在你的“ol”列表变体(就像List<object>似乎允许的那样)中放置任何奇怪的“对象”,因为你的代码会崩溃(因为列表真的是List<string> ,只会接受Stringtypes的对象)。 这就是为什么你不能把你的variables转换成更一般的规范。

在Java上反过来,你没有generics,而是在运行时对象列表,而你真的可以在你所谓的严格types的List中填充任何奇怪的对象。 search“泛化的generics”来查看java的问题的更广泛的讨论…

这种generics的协变是不支持的,但你可以用数组来实现:

 object[] a = new string[] {"spam", "eggs"}; 

C#执行运行时检查,以防止你把一个int放入a

这里是另一个可以隐式转换内容的IList的.NET 3.5解决scheme。

 public IList<B> ConvertIList<D, B>(IList<D> list) where D : B { List<B> newList = new List<B>(); foreach (D item in list) { newList.Add(item); } return newList; } 

(基于Zooba的例子)

我有一个:

 private List<Leerling> Leerlingen = new List<Leerling>(); 

而且我要用在List<object>收集的数据来填充它。最后为我工作的是这个:

 Leerlingen = (List<Leerling>)_DeserialiseerLeerlingen._TeSerialiserenObjecten.Cast<Leerling>(); 

.Cast它传递给你想从这个types获得一个IEnumerabletypes,然后将IEnemuerabletypes转换为你想要的List<>

恩,感谢之前的评论,我find了两种方法找出来。 第一个是获取元素的string列表,然后将其转换为IEnumerable对象列表:

 IEnumerable<object> ob; List<string> st = new List<string>(); ob = st.Cast<object>(); 

第二个是避免IEnumerable对象types,只是将string强制转换为对象types,然后在同一个语句中使用函数“toList()”:

 List<string> st = new List<string>(); List<object> ob = st.Cast<object>().ToList(); 

我更喜欢第二种方式。 我希望这有帮助。

 List<string> sl = new List<string>(); List<object> ol; ol = new List<object>(sl);