我有以下情况,我想在列表中添加一些项目......
List<T> items = new List<T>();
IEnumerable<T> addItems = someCollection.Where(...);
items.AddRange(addItems);
使用此代码,列表中不会添加任何项目,但如果我在Linq语句之后添加.ToList(),则会正确添加项目。我想这是由于延迟执行,但我想如果List.AddRange函数接受一个IEnumerable,它将枚举要添加的项目。
有人可以澄清为什么会这样吗?
答案 0 :(得分:4)
我想这是由于延迟执行,但我认为,鉴于List.AddRange函数接受一个IEnumerable,它将枚举要添加的项目。
确实如此。 ICollection<T>
有一个短路(在这种情况下你不会碰到它),这会导致它使用ICollection<T>.CopyTo
而不是枚举项目,否则,它会枚举集合。 / p>
对于一个工作示例,请尝试:
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();
}
}
这会使用您的确切代码,并打印出500(List<T>
中的正确数量的项目)。
答案 1 :(得分:2)
确实有效。这是一个证明它的单元测试:
[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);
}
}
也许您的特定场景中有些东西无法正常工作。
答案 2 :(得分:2)
我会想到,鉴于List.AddRange函数接受一个 IEnumerable它将枚举要添加的项目。
我尝试了以下内容,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);
答案 3 :(得分:2)
感谢您的回复。我试图简化这个例子的代码,但像往常一样,细节中的魔鬼!
在.Where()语句和AddRange()调用之间,代码是(内心深处)清除源(本例中为“items”)列表。开发人员没有意识到过滤器被推迟到AddRange()调用,此时他们已经清除了源列表。
很高兴知道我没有丢失情节:)