如何初始化一个空的IEnumerable<Object>并允许对其进行Concat操作?

48

我尝试了这段代码来将b添加到books中:

IEnumerable<Book> books =null;
foreach (Book b in context.Books.AsEnumerable())
    if (someConditions)
       books = books.Concat(new[] {b});

但在代码的最后一行给了我这个错误:

System.ArgumentNullException:值不能为空。 参数名称:first

似乎无法将 nullCollection 进行拼接。我正在使用EF,那么我该如何初始化我的 Collection,使其不包含任何内容,而且我可以将其他内容连接到它上面?


1
IEnumerable<Book> books = new List<Book>(); - Nick
30
IEnumerable<Book> books = Enumerable.Empty<Book>(); - Vyacheslav Volkov
3
@VyacheslavVolkov 这应该是一个答案。 - user1908061
var books = context.Books.Where(b=> condition(b)).ToList(); - Damith
3
其他人已经回答了你的问题。但是,通过连接许多类型为Book[]的长度为1的数组来创建IEnumerable<Book>仍然非常低效且有些丑陋。考虑使用Linq中的Where进行书籍过滤,就像@Damith的评论中所示,或者重写循环以使用yield return b;(将此循环提取到一个新方法中,一个称为迭代器块的东西)。 - Jeppe Stig Nielsen
显示剩余5条评论
5个回答

111

看起来你只是想按照某些标准筛选你的内容,比如书籍。

IEnumerable<Book> books = context.Books.Where(b => someConditions);

如果你仍需要空的IEnumerable,你可以直接调用Enumerable.Empty()方法:

IEnumerable<Book> books = Enumerable.Empty<Book>();

28
IEnumerable<Book> books = new List<Book>();

5
这是您试图做的事情:
IEnumerable<Book> books = Enumerable.Empty<Book>();
books = books.Concat(context.Books.AsEnumerable().Where(b => someCondition));

如果您喜欢从零开始,也可以这样做:

IEnumerable<Book> books = null;
var moreBooks = context.Books.AsEnumerable().Where(b => someCondition);
books = books == null ? moreBooks : books.Concat(moreBooks);

虽然我有几个问题,想知道你为什么要/需要以这种方式做事。


4

个人建议直接使用:

IEnumerable<Book> books = new Book[0];

使用列表的方式不如其他方法更好。


1
虽然我仍然会使用Enumerable.Empty<T>而不是这个,因为它避免了创建新的数组实例,但这仍然比根据被接受的答案创建List<T>更好,因为在.NET中有一个优化,可以为零长度的数组缓存枚举器! - AnorZaken
@AnorZaken 我同意 Enumberable.Empty<T> 更好(因为它更具描述性),但请注意它仍然会(懒惰地)创建一个空数组。 - Matthew Watson
1
是的,但它只对每种类型T执行一次,利用类型系统和JIT使其变成惰性和缓存(通用静态只读字段)。因此,“Enumerable.Empty”仍然是最佳选择。(我们不知道会调用多少次那行代码-也许每秒1000次,只有操作员知道。) - AnorZaken

1
您需要创建一个类似于List的IEnumerable空对象books,但需要记得在循环之后调用ToList()方法。例如:
        IEnumerable<int> books = new List<int>();
        IEnumerable<int> books2 = new int[] { 1, 2, 3, 4 };


        foreach (int b in books2)
            if (b > 2)
                books = (new[] { b }).Concat(books);

        books = books.ToList();

3
你可以像Vyacheslav Volkov上面提到的那样使用Enumerable.Empty<Book>()。 - darthkurak

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接