在c#中,为什么不能将List对象存储在List变量中。

时间:2022-01-11 16:04:37

It seems that a List object cannot be stored in a List variable in C#, and can't even be explicitly cast that way.

似乎List对象不能存储在c#中的List变量中,甚至不能以这种方式显式转换。

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

results in Cannot implicitly convert type System.Collections.Generic.List<string> to System.Collections.Generic.List<object>

结果不能隐式地转换类型system . collection . generic。列表 <字符串> System.Collections.Generic.List <对象>

And then...

然后……

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

results in Cannot convert type System.Collections.Generic.List<string> to System.Collections.Generic.List<object>

结果不能转换类型system . collection . generic。列表 <字符串> System.Collections.Generic.List <对象>

Of course, you can do it by pulling everything out of the string list and putting it back in one at a time, but it is a rather convoluted solution.

当然,您可以从字符串列表中取出所有内容,并一次将其放入其中,但这是一个相当复杂的解决方案。

14 个解决方案

#1


35  

Think of it this way, if you were to do such a cast, and then add an object of type Foo to the list, the list of strings is no longer consistent. If you were to iterate the first reference, you would get a class cast exception because once you hit the Foo instance, the Foo could not be converted to string!

这样想,如果您要执行这样的转换,然后向列表中添加一个Foo类型的对象,那么字符串列表将不再一致。如果您要迭代第一个引用,您将得到一个类强制转换异常,因为一旦您点击了Foo实例,Foo就不能被转换为string!

As a side note, I think it would be more significant whether or not you can do the reverse cast:

顺便说一下,我认为你是否可以做反向转换会更重要:

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

I haven't used C# in a while, so I don't know if that is legal, but that sort of cast is actually (potentially) useful. In this case, you are going from a more general class (object) to a more specific class (string) that extends from the general one. In this way, if you add to the list of strings, you are not violating the list of objects.

我已经有一段时间没有使用c#了,所以我不知道这是否合法,但是这种类型的转换实际上(可能)是有用的。在本例中,您将从一个更通用的类(对象)扩展到一个更特定的类(字符串),这个类从通用类扩展而来。这样,如果添加到字符串列表中,就不会违反对象列表。

Does anybody know or can test if such a cast is legal in C#?

有没有人知道或者可以测试这样的演员在c#中是否合法?

#2


35  

If you're using .NET 3.5 have a look at the Enumerable.Cast method. It's an extension method so you can call it directly on the List.

如果您正在使用。net 3.5,请查看一下Enumerable。铸造方法。它是一个扩展方法,所以你可以直接在列表中调用它。

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

It's not exactly what you asked for but should do the trick.

这并不是你想要的,但应该是你想要的。

Edit: As noted by Zooba, you can then call ol.ToList() to get a List

编辑:正如Zooba所指出的,然后您可以调用ol.ToList()来获取一个列表

#3


14  

You cannot cast between generic types with different type parameters. Specialized generic types don't form part of the same inheritance tree and so are unrelated types.

不能在具有不同类型参数的泛型类型之间强制转换。专门化的泛型类型不构成同一继承树的一部分,因此是不相关的类型。

To do this pre-NET 3.5:

要做这个前网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
}

Using Linq:

使用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();

#4


12  

The reason is that a generic class like List<> is, for most purposes, treated externally as a normal class. e.g. when you say List<string>() the compiler says ListString() (which contains strings). [Technical folk: this is an extremely plain-English-ified version of what's going on]

原因是,像List<>这样的泛型类在大多数情况下被外部视为一个普通类。例如,当您说List ()时,编译器会说ListString()(包含字符串)。[技术人员:这是一个非常简单的英文版本]

Consequently, obviously the compiler can't be smart enough to convert a ListString to a ListObject by casting the items of its internal collection.

因此,显然,编译器不能足够智能地将ListString转换为ListObject,从而将其内部集合的项转换为ListObject。

That's why there's extension methods for IEnumerable like Convert() that allow you to easily supply conversion for the items stored inside a collection, which could be as simple as casting from one to another.

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

#5


6  

This has a lot to do with covariance, e.g., generic types are considered as parameters, and if the parameters do not resolve properly to a more specific type then the operation fails. The implication of such is that you really cannot cast to a more general type like object. And as stated by Rex, the List object won't convert each object for you.

这与协方差有很大关系,例如,泛型类型被视为参数,如果参数不能正确解析为更特定的类型,那么操作将失败。它的含义是,您真的不能将对象转换为更一般的类型。正如Rex所说,列表对象不会为您转换每个对象。

You might want to try the ff code instead:

你可以试试ff代码:

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

or:

或者:

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

ol will (theoretically) copy all the contents of sl without problems.

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

#6


5  

Yes, you can, from .NET 3.5:

是的,你可以,从。net 3.5:

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

#7


3  

Mike - I believe contravariance isn't allowed in C# either

迈克——我相信在c#中也不允许逆变

See Generic type parameter variance in the CLR for some more info.

有关更多信息,请参见CLR中的泛型类型参数方差。

#8


2  

I think that this (contravariance) will actually be supported in C# 4.0. http://blogs.msdn.com/charlie/archive/2008/10/27/linq-farm-covariance-and-contravariance-in-visual-studio-2010.aspx

我认为c# 4.0实际上会支持这个(逆变)。http://blogs.msdn.com/charlie/archive/2008/10/27/linq -农业-协方差和逆变性-在- 2010. aspx -视觉工作室

#9


1  

That's actually so that you don't try to put any odd "object" in your "ol" list variant (as List<object> would seem to allow) - because your code would crash then (because the list really is List<string> and will only accept String type objects). That's why you can't cast your variable to a more general specification.

这实际上是为了避免在“ol”列表变量中添加任何奇怪的“对象”(如list 会允许的)—因为您的代码会崩溃(因为列表实际上是list ,并且只接受string类型的对象)。这就是为什么您不能将变量转换为更一般的规范。

On Java it's the other way around, you don't have generics, and instead everything is List of object at runtime, and you really can stuff any strange object in your supposedly-strictly typed List. Search for "Reified generics" to see a wider discussion of java's problem...

在Java中,情况正好相反,你没有泛型,而是在运行时,所有东西都是对象列表,你可以在你假设的严格类型列表中填充任何奇怪的对象。搜索“具体化的泛型”,查看对java问题的更广泛讨论……

#10


1  

Such covariance on generics is not supported, but you can actually do this with arrays:

这种对泛型的协方差是不支持的,但是你可以用数组来做:

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

C# performs runtime checks to prevent you from putting, say, an int into a.

c#执行运行时检查,以防止您将int放入a中。

#11


0  

Here is another pre-.NET 3.5 solution for any IList whose contents can be cast implicitly.

这里是另一个前置。NET 3.5任何可以隐式施放内容的IList的解决方案。

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;
}

(Based on Zooba's example)

(基于Zooba的例子)

#12


0  

I have a:

我有一个:

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

And I was going to fill it with data collected in an List<object> What finally worked for me was this one:

我要用一个列表中收集的数据填充它最终对我起作用的是这个:

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

.Cast it to the type you want to get an IEnumerable from that type, then typecast the IEnemuerable to the List<> you want.

将其转换为您想从该类型中获得IEnumerable的类型,然后将IEnemuerable类型转换为您想要的列表<>。

#13


0  

Mm, thanks to previous comments I found two ways to find it out. The first one is getting the string list of elements and then casting it to IEnumerable object list:

嗯,多亏了之前的评论,我找到了两种找到答案的方法。第一个是获取元素的字符串列表,然后将其转换为IEnumerable对象列表:

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

And the second one is avoiding the IEnumerable object type, just casting the string to object type and then using the function "toList()" in the same sentence:

第二个是避免IEnumerable类型,就是将字符串转换为object类型,然后在同一个句子中使用toList()函数:

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

I like more the second way. I hope this helps.

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

#14


0  

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

#1


35  

Think of it this way, if you were to do such a cast, and then add an object of type Foo to the list, the list of strings is no longer consistent. If you were to iterate the first reference, you would get a class cast exception because once you hit the Foo instance, the Foo could not be converted to string!

这样想,如果您要执行这样的转换,然后向列表中添加一个Foo类型的对象,那么字符串列表将不再一致。如果您要迭代第一个引用,您将得到一个类强制转换异常,因为一旦您点击了Foo实例,Foo就不能被转换为string!

As a side note, I think it would be more significant whether or not you can do the reverse cast:

顺便说一下,我认为你是否可以做反向转换会更重要:

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

I haven't used C# in a while, so I don't know if that is legal, but that sort of cast is actually (potentially) useful. In this case, you are going from a more general class (object) to a more specific class (string) that extends from the general one. In this way, if you add to the list of strings, you are not violating the list of objects.

我已经有一段时间没有使用c#了,所以我不知道这是否合法,但是这种类型的转换实际上(可能)是有用的。在本例中,您将从一个更通用的类(对象)扩展到一个更特定的类(字符串),这个类从通用类扩展而来。这样,如果添加到字符串列表中,就不会违反对象列表。

Does anybody know or can test if such a cast is legal in C#?

有没有人知道或者可以测试这样的演员在c#中是否合法?

#2


35  

If you're using .NET 3.5 have a look at the Enumerable.Cast method. It's an extension method so you can call it directly on the List.

如果您正在使用。net 3.5,请查看一下Enumerable。铸造方法。它是一个扩展方法,所以你可以直接在列表中调用它。

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

It's not exactly what you asked for but should do the trick.

这并不是你想要的,但应该是你想要的。

Edit: As noted by Zooba, you can then call ol.ToList() to get a List

编辑:正如Zooba所指出的,然后您可以调用ol.ToList()来获取一个列表

#3


14  

You cannot cast between generic types with different type parameters. Specialized generic types don't form part of the same inheritance tree and so are unrelated types.

不能在具有不同类型参数的泛型类型之间强制转换。专门化的泛型类型不构成同一继承树的一部分,因此是不相关的类型。

To do this pre-NET 3.5:

要做这个前网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
}

Using Linq:

使用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();

#4


12  

The reason is that a generic class like List<> is, for most purposes, treated externally as a normal class. e.g. when you say List<string>() the compiler says ListString() (which contains strings). [Technical folk: this is an extremely plain-English-ified version of what's going on]

原因是,像List<>这样的泛型类在大多数情况下被外部视为一个普通类。例如,当您说List ()时,编译器会说ListString()(包含字符串)。[技术人员:这是一个非常简单的英文版本]

Consequently, obviously the compiler can't be smart enough to convert a ListString to a ListObject by casting the items of its internal collection.

因此,显然,编译器不能足够智能地将ListString转换为ListObject,从而将其内部集合的项转换为ListObject。

That's why there's extension methods for IEnumerable like Convert() that allow you to easily supply conversion for the items stored inside a collection, which could be as simple as casting from one to another.

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

#5


6  

This has a lot to do with covariance, e.g., generic types are considered as parameters, and if the parameters do not resolve properly to a more specific type then the operation fails. The implication of such is that you really cannot cast to a more general type like object. And as stated by Rex, the List object won't convert each object for you.

这与协方差有很大关系,例如,泛型类型被视为参数,如果参数不能正确解析为更特定的类型,那么操作将失败。它的含义是,您真的不能将对象转换为更一般的类型。正如Rex所说,列表对象不会为您转换每个对象。

You might want to try the ff code instead:

你可以试试ff代码:

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

or:

或者:

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

ol will (theoretically) copy all the contents of sl without problems.

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

#6


5  

Yes, you can, from .NET 3.5:

是的,你可以,从。net 3.5:

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

#7


3  

Mike - I believe contravariance isn't allowed in C# either

迈克——我相信在c#中也不允许逆变

See Generic type parameter variance in the CLR for some more info.

有关更多信息,请参见CLR中的泛型类型参数方差。

#8


2  

I think that this (contravariance) will actually be supported in C# 4.0. http://blogs.msdn.com/charlie/archive/2008/10/27/linq-farm-covariance-and-contravariance-in-visual-studio-2010.aspx

我认为c# 4.0实际上会支持这个(逆变)。http://blogs.msdn.com/charlie/archive/2008/10/27/linq -农业-协方差和逆变性-在- 2010. aspx -视觉工作室

#9


1  

That's actually so that you don't try to put any odd "object" in your "ol" list variant (as List<object> would seem to allow) - because your code would crash then (because the list really is List<string> and will only accept String type objects). That's why you can't cast your variable to a more general specification.

这实际上是为了避免在“ol”列表变量中添加任何奇怪的“对象”(如list 会允许的)—因为您的代码会崩溃(因为列表实际上是list ,并且只接受string类型的对象)。这就是为什么您不能将变量转换为更一般的规范。

On Java it's the other way around, you don't have generics, and instead everything is List of object at runtime, and you really can stuff any strange object in your supposedly-strictly typed List. Search for "Reified generics" to see a wider discussion of java's problem...

在Java中,情况正好相反,你没有泛型,而是在运行时,所有东西都是对象列表,你可以在你假设的严格类型列表中填充任何奇怪的对象。搜索“具体化的泛型”,查看对java问题的更广泛讨论……

#10


1  

Such covariance on generics is not supported, but you can actually do this with arrays:

这种对泛型的协方差是不支持的,但是你可以用数组来做:

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

C# performs runtime checks to prevent you from putting, say, an int into a.

c#执行运行时检查,以防止您将int放入a中。

#11


0  

Here is another pre-.NET 3.5 solution for any IList whose contents can be cast implicitly.

这里是另一个前置。NET 3.5任何可以隐式施放内容的IList的解决方案。

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;
}

(Based on Zooba's example)

(基于Zooba的例子)

#12


0  

I have a:

我有一个:

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

And I was going to fill it with data collected in an List<object> What finally worked for me was this one:

我要用一个列表中收集的数据填充它最终对我起作用的是这个:

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

.Cast it to the type you want to get an IEnumerable from that type, then typecast the IEnemuerable to the List<> you want.

将其转换为您想从该类型中获得IEnumerable的类型,然后将IEnemuerable类型转换为您想要的列表<>。

#13


0  

Mm, thanks to previous comments I found two ways to find it out. The first one is getting the string list of elements and then casting it to IEnumerable object list:

嗯,多亏了之前的评论,我找到了两种找到答案的方法。第一个是获取元素的字符串列表,然后将其转换为IEnumerable对象列表:

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

And the second one is avoiding the IEnumerable object type, just casting the string to object type and then using the function "toList()" in the same sentence:

第二个是避免IEnumerable类型,就是将字符串转换为object类型,然后在同一个句子中使用toList()函数:

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

I like more the second way. I hope this helps.

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

#14


0  

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