C# 如何有效地投射 List<T> ?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/504729/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 05:57:39  来源:igfitidea点击:

How do I cast a List<T> effectively?

c#linq-to-sql

提问by bentford

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:

此列表来自 Linq-to-Sql 查询:

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

采纳答案by Helen Toomik

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

.OfType<T> 和 .Cast<T> 都会返回一个 T 的列表,但是两种方法的含义不同。

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

list.OfType()过滤原始列表并返回所有属于 T 类型的项目,并跳过不属于该类型的项目。

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

list.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();

回答by Amy B

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

回答by TheSmurf

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

回答by Arjan Einbu

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”部分来代替返回 IDataField 吗?像这样的东西:

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

回答by CubanX

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

回答by Paul Brinkley

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

以防万一:我几乎没有 C# 经验,但是如果这种泛型构造的含义与它在 Java 中的含义相同,那么您必须创建一个由超类型参数化的全新 List。换句话说,如果 的每个实例Bangle也是 的实例Akthud则不意味着每个List<Bangle>也是List<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 Akthudto it - but now the first reference has a List<Bangle>whose members are not all Bangles. Violation!

这样做的原因是您可以有两个对 this 的引用List<Bangle>。如果第二个引用强制转换,然后将其作为 a 引用List<Akthud>,则允许向其添加 an Akthud- 但现在第一个引用具有 a ,List<Bangle>其成员不全是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# 泛型的语义,我希望有人在评论中纠正我!]

回答by husayt

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:

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

回答by Seyedraouf Modarresi

I have the following string

我有以下字符串

 var str = "2 4 7 8 10";

when I cast as follow

当我投如下

var numbersInt2 = numbers.Split(' ')
                .ToList().Cast<int>().ToList();

it returns an exception but

它返回一个异常但是

System.InvalidCastException: 'Specified cast is not valid.'

System.InvalidCastException: '指定的转换无效。'

, if using the following

, 如果使用以下

var numbersInt = numbers.Split(' ')
                .ToList().ConvertAll(int.Parse);

it works.

有用。