C# List.AddRange和IEnumerable<;T>;参数不工作?

C# List.AddRange和IEnumerable<;T>;参数不工作?,c#,list,ienumerable,deferred,addrange,C#,List,Ienumerable,Deferred,Addrange,我有下面的场景,我想在列表中添加一些项目 List<T> items = new List<T>(); IEnumerable<T> addItems = someCollection.Where(...); items.AddRange(addItems); List items=newlist(); IEnumerable addItems=someCollection.Where(…); 项目。添加范围(添加项); 使用此代码,不会将任何项添加到列表

我有下面的场景,我想在列表中添加一些项目

List<T> items = new List<T>();
IEnumerable<T> addItems = someCollection.Where(...);
items.AddRange(addItems);
List items=newlist();
IEnumerable addItems=someCollection.Where(…);
项目。添加范围(添加项);
使用此代码,不会将任何项添加到列表中,但如果在Linq语句之后添加.ToList(),则这些项将正确添加。我猜这是由于延迟执行,但我认为如果List.AddRange函数接受IEnumerable,它将枚举要添加的项

有人能解释一下为什么会这样吗

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

是的。
ICollection
(在本例中,您不会点击它)存在短路,这将导致它使用而不是枚举项,否则,它将枚举集合

要获得一个有效的示例,请尝试:

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();
    }
}
使用系统;
使用System.Linq;
使用System.Collections.Generic;
内部课程计划
{
私有静态列表运行查询(IEnumerable someCollection,Func谓词)
{
列表项=新列表();
IEnumerable addItems=someCollection.Where(谓词);
项目。添加范围(添加项);
退货项目;
}
静态void Main()
{
var值=可枚举范围(0,1000);
列表结果=运行查询(值,i=>i>=500);
Console.WriteLine(results.Count);
Console.WriteLine(“按键退出:”);
Console.ReadKey();
}
}

这将使用您的确切代码,并将打印出500(列表中正确数量的项目)。

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

[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);
    }
}
[TestFixture]
公共类范围测试
{
[测试]
public void AddRange()
{
var list=新列表();
var someCollection=新列表{1,2,3};
var subItems=someCollection.Where(x=>x>1);
列表.添加范围(子项);
Assert.AreEqual(2,list.Count);
}
}
也许在你的特定场景中有一些东西不能正常工作

我本以为给定List.AddRange函数接受 IEnumerable表示它将枚举要添加的项

我尝试了下面的方法,
AddRange(IEnumerable)
确实有效

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);
List someCollection=新列表{“A”、“B”、“C”};
列表项=新列表();
IEnumerable addItems=someCollection.Where(x=>x!=“”);
项目。添加范围(添加项);

感谢您的回复。我试图简化这个例子的代码,但和往常一样,魔鬼在细节中

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


很高兴知道我没有丢失绘图:)

您如何看待“未添加项目”,因为它应该添加项目?someCollection的类型是什么?请提供实际工作的代码,我不太确定需要在哪里添加ToList。someCollection是否是IQueryable,是否有可能存在未正确实现的Linq提供程序?OP示例中的someCollection可能属于已使用空定义实现了CopyTo的某种类型?@DanTao是-可能还有其他情况发生。但是,一般来说,这确实适用于
IEnumerable
——这不是一个“延迟执行”问题。@DanTao(请注意,这需要OP有自己的“Where”方法来创建
ICollection
,并使用奇怪的实现)对。看起来OP更可能是搞错了什么。。。但谁知道呢。