带有 IEnumerable 参数的列表添加范围<T>不起作用?



我有以下场景,我想向列表中添加一些项。。。

List<T> items = new List<T>();
IEnumerable<T> addItems = someCollection.Where(...);
items.AddRange(addItems);

使用此代码,不会将任何项添加到列表中,但如果在Linq语句之后添加.ToList(),则会正确添加这些项。我想这是由于延迟执行,但我认为如果List.AddRange函数接受IEnumerable,它会枚举要添加的项。

有人能澄清为什么会发生这种事吗?

我想这是由于延迟执行,但我认为如果List.AddRange函数接受IEnumerable,它会枚举要添加的项。

确实如此。ICollection<T>短路(在这种情况下不会碰到),这将导致它使用ICollection<T>.CopyTo而不是枚举项,但否则,它将枚举集合。

对于一个工作示例,请尝试:

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>中的正确项目数)。

我本以为给定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);

它确实有效。这里有一个单元测试证明了这一点:

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

也许在你的特定场景中有一些东西不能正常工作。

感谢您的回复。我试着简化这个例子的代码,但和往常一样,关键在于细节!

在.Where()语句和AddRange()调用之间,代码正在(深层次)清除源(本例中为"items")列表。开发人员没有意识到过滤器被推迟到AddRange()调用,此时他们已经清除了源列表。

很高兴知道我没有失去这个情节:)

相关内容

  • 没有找到相关文章

最新更新