C# 带有 IEnumerable<T> 参数的 List.AddRange 不起作用?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11750688/
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
List.AddRange with IEnumerable<T> parameter not working?
提问by John
I have the following scenario where I want to add some items to a List...
我有以下场景,我想将一些项目添加到列表中...
List<T> items = new List<T>();
IEnumerable<T> addItems = someCollection.Where(...);
items.AddRange(addItems);
Using this code, no items are added to the list but if I add a .ToList() after then Linq statement then the items are added correctly. I guess this is due to deferred execution but I would have thought that given the List.AddRange function accepts an IEnumerable that it would enumerate the items to be added.
使用此代码,不会将任何项目添加到列表中,但如果我在 Linq 语句之后添加 .ToList() ,则项目将正确添加。我猜这是由于延迟执行,但我认为如果 List.AddRange 函数接受一个 IEnumerable,它将枚举要添加的项目。
Can someone please clear up why this happens?
有人可以澄清为什么会发生这种情况吗?
采纳答案by John
Thanks for the replies. I tried to simplify the code for this example but as usual, the devil's in the details!
感谢您的回复。我试图简化这个例子的代码,但像往常一样,细节决定成败!
Between the .Where() statement and the AddRange() call the code was (deep down) clearing the source ('items' in this example) list. The developer didn't realise that the filter was deferred until the AddRange() call at which point they had already cleared the source list.
在 .Where() 语句和 AddRange() 调用之间,代码是(深入地)清除源(本例中的“项目”)列表。开发人员没有意识到过滤器被推迟到 AddRange() 调用,此时他们已经清除了源列表。
Glad to know I haven't lost the plot :)
很高兴知道我没有失去情节:)
回答by Reed Copsey
I guess this is due to deferred execution but I would have thought that given the List.AddRange function accepts an IEnumerable that it would enumerate the items to be added.
我猜这是由于延迟执行,但我认为如果 List.AddRange 函数接受一个 IEnumerable,它将枚举要添加的项目。
It does. There is a short circuit for ICollection<T>(which you wouldn't hit in this case), which would cause it to use ICollection<T>.CopyToinstead of enumerating the items, but otherwise, it will enumerate the collection.
确实如此。有一个短路ICollection<T>(在这种情况下你不会命中),这将导致它使用ICollection<T>.CopyTo而不是枚举项目,否则,它将枚举集合。
For a working example, try:
对于一个工作示例,请尝试:
using System;
using System.Linq;
using System.Collections.Generic;
internal class Program
{
private static List<T> RunQuery<T>(IEnumerable<T> someCollection, Func<T, bool> predicate)
{
List<T> items = new List<T>();
IEnumerable<T> addItems = someCollection.Where(predicate);
items.AddRange(addItems);
return items;
}
static void Main()
{
var values = Enumerable.Range(0, 1000);
List<int> results = RunQuery(values, i => i >= 500);
Console.WriteLine(results.Count);
Console.WriteLine("Press key to exit:");
Console.ReadKey();
}
}
This uses your exact code, and will print out 500 (the proper number of items in the List<T>).
这将使用您的确切代码,并将打印出 500( 中的正确项目数List<T>)。
回答by Pablo Romeo
It does work. Here's a unit test that proves it:
它确实有效。这是一个证明它的单元测试:
[TestFixture]
public class AddRangeTest
{
[Test]
public void AddRange()
{
var list = new List<int>();
var someCollection = new List<int> { 1, 2, 3 };
var subItems = someCollection.Where(x => x > 1);
list.AddRange(subItems);
Assert.AreEqual(2, list.Count);
}
}
Maybe there's something in your specific scenario that is not working correctly.
也许您的特定场景中有些东西无法正常工作。
回答by HatSoft
I would have thought that given the List.AddRange function accepts an IEnumerable that it would enumerate the items to be added.
我原以为 List.AddRange 函数接受一个 IEnumerable,它会枚举要添加的项目。
I tried the below and AddRange(IEnumerable<T>)does work
我尝试了以下并且AddRange(IEnumerable<T>)确实有效
List<string> someCollection = new List<string>{"A", "B", "C"};
List<string> items = new List<string>();
IEnumerable<string> addItems = someCollection.Where(x => x != "");
items.AddRange(addItems);

