C# 如何将 List<object> 转换为 List<SomethingElse>

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8933434/
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-09 05:17:00  来源:igfitidea点击:

How to cast List<object> to List<SomethingElse>

c#generics

提问by Ian Boyd

How can i cast a List<object>to List<SomethingElse>?

我怎样才能投射List<object>List<SomethingElse>

(where SomethingElseis known to descend from object)

已知从哪里SomethingElse下降object



Bonus Chatter

奖金喋喋不休

Casting the list:

铸造名单:

List<Object> first = ...;

List<SomethingElse> second = (List<SomethingElse>)first;

doesn't work:

不起作用:

Cannot convert type 'System.Collections.Generic.List' to 'System.Collections.Generic.List'

无法将类型“System.Collections.Generic.List”转换为“System.Collections.Generic.List”

Casting the list:

铸造名单:

List<SomethingElse> second = first.Cast<SomethingElse>();

doesn't work:

不起作用:

Cannot implicitely convert type 'System.Collections.Generic.List' to 'System.Collections.Generic.List'

无法将类型“System.Collections.Generic.List”隐式转换为“System.Collections.Generic.List”

i don't actually need the full List<T>object, just an ICollection<T>will do:

我实际上并不需要完整的List<T>对象,只是ICollection<T>会做:

ICollection<SomethingElse> second = first;
ICollection<SomethingElse> second = (ICollection<SomethingElse>)first;
ICollection<SomethingElse> second = first.Cast<SomethingElse>();

don't work.

不工作。

采纳答案by Douglas

LINQ, as implemented through the extension methods within the Enumerableclass, relies on deferred execution:

通过类中的扩展方法实现的 LINQEnumerable依赖于延迟执行:

Methods that are used in a query that returns a sequence of values do not consume the target data until the query object is enumerated. This is known as deferred execution.

在查询对象被枚举之前,在返回值序列的查询中使用的方法不会使用目标数据。这称为延迟执行。

Cast<T>does not create a new list immediately, but rather stores all the information that is required to perform the action. The list would only get enumerated when required (for example, through a foreachstatement).

Cast<T>不会立即创建新列表,而是存储执行操作所需的所有信息。该列表只会在需要时被枚举(例如,通过foreach语句)。

In your case, if you simply intend to iterate over the sequence, you should consider sticking to the IEnumerable<T>interface, which is the declared return type of Cast<T>:

在您的情况下,如果您只是打算迭代序列,您应该考虑坚持使用IEnumerable<T>接口,这是声明的返回类型Cast<T>

IEnumerable<SomethingElse> second = first.Cast<SomethingElse>();
foreach (SomethingElse se in second)
{
    // ...
}

This is efficient, since it only performs the cast as each item is iterated.

这是有效的,因为它只在迭代每个项目时执行转换。

If you're convinced you want a new list to be created immediately, use ToList:

如果您确信要立即创建一个新列表,请使用ToList

List<SomethingElse> second = first.Cast<SomethingElse>().ToList();

Edit: Replying to point posted in comment:

编辑:回复发表在评论中的点:

It depends on what you mean by “a list that can be modified”. There are several LINQ query operators that will allow you to alter the definition of your query further. For example, if you want to remove all SomethingElseelements whose IsDeletedproperty is true, you can use the Whereoperator:

这取决于您所说的“可以修改的列表”是什么意思。有几个 LINQ 查询运算符可让您进一步更改查询的定义。例如,如果要删除属性为 的所有SomethingElse元素,IsDeletedtrue可以使用Where运算符:

IEnumerable<SomethingElse> second = first.Cast<SomethingElse>();
second = second.Where(element => !element.IsDeleted);

If you want to add a sequence of new elements, you can use the Concatoperator:

如果要添加一系列新元素,可以使用Concat运算符:

second = second.Concat(anotherCollectionOfSomethingElse);

If you want to sort your sequence in ascending order of ID, use the OrderByoperator:

如果要按 的升序对序列进行排序ID,请使用OrderBy运算符:

second = second.OrderBy(element => element.ID);

Each time, we're applying a query operator over the former definition of our query, and assigning the new (composite) query to our secondvariable. LINQ would store all your operators in the query definition. Then, when the sequence is actually enumerated (for example, through a foreachor ToList), it would give you the composite result of your sequence, with all the query operators applied in order.

每次,我们都在查询的先前定义上应用查询运算符,并将新的(复合)查询分配给我们的second变量。LINQ 会将所有运算符存储在查询定义中。然后,当实际枚举序列时(例如,通过 aforeachToList),它将为您提供序列的复合结果,并按顺序应用所有查询运算符。

As with all cases of deferred execution / lazy evaluation, be careful not to go overboard with this. If, for example, you're going to apply a Whereoperator which will reduce the size of your sequence drastically, it might make sense to execute the query eagerly and store the enumerated list instead.

与所有延迟执行/延迟评估的情况一样,注意不要过度使用它。例如,如果您要应用一个Where运算符来显着减小序列的大小,那么急切地执行查询并改为存储枚举列表可能是有意义的。

回答by Matt Dillard

I think you're close with the Cast<T>expression. The difference is that Cast<T>returns an IEnumerable<T>, not a List<T>.

我认为你很接近这个Cast<T>表达。不同之处在于Cast<T>返回的是IEnumerable<T>,而不是List<T>

Try this:

尝试这个:

IEnumerable<SomethingElse> second = first.Cast<SomethingElse>();

You can get a list by doing something similar:

您可以通过执行类似操作来获取列表:

List<SomethingElse> second = first.Cast<SomethingElse>().ToList();

回答by Charles Lambert

You have the option of using either Castor OfType. Castwill throw an exception if you cannot cast to the type specified. OfTypeon the other hand will return only those items in the list that can be cast to the specified type. I would recommend using OfTypein your situation.

您可以选择使用CastOfTypeCast如果您无法强制转换为指定的类型,则会抛出异常。OfType另一方面,将仅返回列表中可以强制转换为指定类型的项目。我建议OfType在您的情况下使用。

List<Foo> fooList = myList.OfType<Foo>().ToList();