我如何有效地投出一个列表 ?

时间:2021-08-04 21:15:08

I have a

我有一个

List<InputField> 

but I need a

但是我需要一个

List<IDataField>  

Is there a way to cast this in c#? Or use Linq to get same result?

在c#中是否有这样的方法?或者用Linq来得到相同的结果?

I have two classes that implement the same interface:

我有两个类实现了相同的接口:

interface IDataField { }
class InputField : IDataField { }
class PurchaseField : IDataField { }

This List comes from a Linq-to-Sql query:

这个列表来自于linqto - sql查询:

List<InputField> list = (from i .... select i).ToList();

7 个解决方案

#1


36  

Both .OfType<T> and .Cast<T> will return a list of T, but the meaning of the two methods is different.

. oftype 和。cast 将返回T的列表,但是这两种方法的含义不同。

list.OfType filters the original list and returns all items which are of type T, and skips the ones that are not of that type.

列表。OfType筛选原始列表并返回T类型的所有项,并跳过不属于该类型的项。

list.Cast casts all items in the original list to type T, and throws an exception for items which cannot be cast to that type.

列表。Cast将原始列表中的所有项都转换为T类型,并对不能被转换为该类型的项抛出异常。

In your case both would give the same result, but using .Cast would communicate your intent a lot more clearly, so I would recommend using that.

在你的案例中,两者都会给出相同的结果,但是使用。cast会更清楚地表达你的意图,所以我建议使用它。

List<InputField> list = (from i .... select i).Cast<IDataField>.ToList();

#2


11  

List<InputField> raw = (from i .... select i).ToList();
List<IDataField> result = raw.OfType<IDataField>().ToList();

#3


6  

You could also use List.ConvertAll.

你也可以使用List.ConvertAll。

Documentation: http://msdn.microsoft.com/en-us/library/73fe8cwf.aspx

文档:http://msdn.microsoft.com/en-us/library/73fe8cwf.aspx

Example:

例子:

List<IDataField> newList = oldList.ConvertAll(i => i as IDataField);

#4


5  

Since the list is coming from

因为名单是来自于。

List<InputField> list = (from i .... select i).ToList();

Couldn't you just fix the "select i" part to instead return IDataField instead? Something like this:

难道你不能把“select i”部分改为返回idat吗?是这样的:

List<InputField> list = (from i .... select (IDataField)i).ToList();

If that doesn't work, perhaps the "Cast" extension to IEnumerable will work:

如果这不起作用,可能对IEnumerable的“Cast”扩展将起作用:

List<DataField> list2 = list.Cast<IDataField>();

#5


3  

Just in case: I've little C# experience, but if this generic construction means the same thing it does in Java, then you must create a whole new List parametrized by the supertype. In other words, if every instance of Bangle is also an instance of Akthud, it does not follow that every List<Bangle> is also a List<Akthud>.

以防万一:我没有c#经验,但是如果这个通用的构造方法和它在Java中一样,那么您必须创建一个由超类型参数化的完整的新列表。换句话说,如果Bangle的每个实例都是Akthud的实例,那么它并不遵循每个列表 也是一个列表

The reason for this is that you can have two references to this List<Bangle>. If the second reference casts and then refers to it as a List<Akthud>, then it is permitted to add an Akthud to it - but now the first reference has a List<Bangle> whose members are not all Bangles. Violation!

这样做的原因是您可以对这个列表有两个引用 。如果第二个引用类型转换,然后将其称为列表 ,则允许添加Akthud—但是现在第一个引用有一个列表 ,其成员并非都是Bangles。违反!

That being said, David B's answer should indeed do what you want, correctly, AFAICT. (It looks like a copy operation.)

话虽如此,大卫·B的回答确实应该做你想做的,正确的,AFAICT。(它看起来像一个复制操作。)

[And if I'm misunderstanding the semantics of C# generics, I hope someone corrects me in a comment!]

[如果我误解了c#泛型的语义,我希望有人在评论中纠正我!]

#6


1  

I don't know that a direct cast would have the desired effect. The rare few times I've done this, it's usually something like:

我不知道直接施放会有什么效果。很少有几次我这样做,通常是这样的:

List<InputField> list = .....
List<IDataField> list2 = new (List<IDataField>((IDataField[])list.ToArray()));

#7


1  

ConvertAll seems like a better solution, since it doesn't depend on Linq library and is shorter and more intuitive.

ConvertAll似乎是一个更好的解决方案,因为它不依赖于Linq库,而且更短更直观。

But both of them are rather workarounds, than solutions. Both of them create a new collection with the same data. There should be a support for generic covariance in .net, i.e. upcasting in the generic collections, which would allow you to do that naturally. For example:

但它们都是解决问题的办法,而不是解决方案。它们都使用相同的数据创建一个新的集合。在。net中应该支持通用的协方差,即在泛型集合中向上转换,这将允许您自然地进行。例如:

List<IDataField> ls = (List<IDataField>)List<InputField>

From my search so far, my conclusion, is that .Net as of 3.5 doesn't support this feature. Hence we have to end up with workarounds.

从我的搜索到目前为止,我的结论是,. net 3.5不支持这个特性。因此,我们不得不以变通的方式结束。

These are the discussions on the topic:

这些是关于这个主题的讨论:

#1


36  

Both .OfType<T> and .Cast<T> will return a list of T, but the meaning of the two methods is different.

. oftype 和。cast 将返回T的列表,但是这两种方法的含义不同。

list.OfType filters the original list and returns all items which are of type T, and skips the ones that are not of that type.

列表。OfType筛选原始列表并返回T类型的所有项,并跳过不属于该类型的项。

list.Cast casts all items in the original list to type T, and throws an exception for items which cannot be cast to that type.

列表。Cast将原始列表中的所有项都转换为T类型,并对不能被转换为该类型的项抛出异常。

In your case both would give the same result, but using .Cast would communicate your intent a lot more clearly, so I would recommend using that.

在你的案例中,两者都会给出相同的结果,但是使用。cast会更清楚地表达你的意图,所以我建议使用它。

List<InputField> list = (from i .... select i).Cast<IDataField>.ToList();

#2


11  

List<InputField> raw = (from i .... select i).ToList();
List<IDataField> result = raw.OfType<IDataField>().ToList();

#3


6  

You could also use List.ConvertAll.

你也可以使用List.ConvertAll。

Documentation: http://msdn.microsoft.com/en-us/library/73fe8cwf.aspx

文档:http://msdn.microsoft.com/en-us/library/73fe8cwf.aspx

Example:

例子:

List<IDataField> newList = oldList.ConvertAll(i => i as IDataField);

#4


5  

Since the list is coming from

因为名单是来自于。

List<InputField> list = (from i .... select i).ToList();

Couldn't you just fix the "select i" part to instead return IDataField instead? Something like this:

难道你不能把“select i”部分改为返回idat吗?是这样的:

List<InputField> list = (from i .... select (IDataField)i).ToList();

If that doesn't work, perhaps the "Cast" extension to IEnumerable will work:

如果这不起作用,可能对IEnumerable的“Cast”扩展将起作用:

List<DataField> list2 = list.Cast<IDataField>();

#5


3  

Just in case: I've little C# experience, but if this generic construction means the same thing it does in Java, then you must create a whole new List parametrized by the supertype. In other words, if every instance of Bangle is also an instance of Akthud, it does not follow that every List<Bangle> is also a List<Akthud>.

以防万一:我没有c#经验,但是如果这个通用的构造方法和它在Java中一样,那么您必须创建一个由超类型参数化的完整的新列表。换句话说,如果Bangle的每个实例都是Akthud的实例,那么它并不遵循每个列表 也是一个列表

The reason for this is that you can have two references to this List<Bangle>. If the second reference casts and then refers to it as a List<Akthud>, then it is permitted to add an Akthud to it - but now the first reference has a List<Bangle> whose members are not all Bangles. Violation!

这样做的原因是您可以对这个列表有两个引用 。如果第二个引用类型转换,然后将其称为列表 ,则允许添加Akthud—但是现在第一个引用有一个列表 ,其成员并非都是Bangles。违反!

That being said, David B's answer should indeed do what you want, correctly, AFAICT. (It looks like a copy operation.)

话虽如此,大卫·B的回答确实应该做你想做的,正确的,AFAICT。(它看起来像一个复制操作。)

[And if I'm misunderstanding the semantics of C# generics, I hope someone corrects me in a comment!]

[如果我误解了c#泛型的语义,我希望有人在评论中纠正我!]

#6


1  

I don't know that a direct cast would have the desired effect. The rare few times I've done this, it's usually something like:

我不知道直接施放会有什么效果。很少有几次我这样做,通常是这样的:

List<InputField> list = .....
List<IDataField> list2 = new (List<IDataField>((IDataField[])list.ToArray()));

#7


1  

ConvertAll seems like a better solution, since it doesn't depend on Linq library and is shorter and more intuitive.

ConvertAll似乎是一个更好的解决方案,因为它不依赖于Linq库,而且更短更直观。

But both of them are rather workarounds, than solutions. Both of them create a new collection with the same data. There should be a support for generic covariance in .net, i.e. upcasting in the generic collections, which would allow you to do that naturally. For example:

但它们都是解决问题的办法,而不是解决方案。它们都使用相同的数据创建一个新的集合。在。net中应该支持通用的协方差,即在泛型集合中向上转换,这将允许您自然地进行。例如:

List<IDataField> ls = (List<IDataField>)List<InputField>

From my search so far, my conclusion, is that .Net as of 3.5 doesn't support this feature. Hence we have to end up with workarounds.

从我的搜索到目前为止,我的结论是,. net 3.5不支持这个特性。因此,我们不得不以变通的方式结束。

These are the discussions on the topic:

这些是关于这个主题的讨论: