48

I tried this code for adding b to books:

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

but gives me this error on last line of code:

System.ArgumentNullException: Value cannot be null. Parameter name: first

it seems that null Collection could not concatenated. I use EF,so how should I initialize my Collection that have no thing in it and I could concatenate to it?

Majid
  • 13,853
  • 15
  • 77
  • 113
  • you can not run method `Concat` on null – Kamil Budziewski Jul 24 '13 at 10:13
  • 1
    IEnumerable books = new List(); – Nick Jul 24 '13 at 10:14
  • @wudzik Ok now what should I do instead? – Majid Jul 24 '13 at 10:14
  • Nick gave you answer first :) – Kamil Budziewski Jul 24 '13 at 10:15
  • 30
    `IEnumerable books = Enumerable.Empty();` – Vyacheslav Volkov Jul 24 '13 at 10:15
  • 3
    @VyacheslavVolkov That should be an answer. – user1908061 Jul 24 '13 at 10:18
  • `var books = context.Books.Where(b=> condition(b)).ToList();` – Damith Jul 24 '13 at 10:23
  • 3
    Others have answered your question. But it's still very inefficient, and somewhat ugly, to create an `IEnumerable` by concatting a lot of length-1 arrays of type `Book[]`. Consider filtering your books with Linq `Where` as in @Damith's comment, or maybe rewrite to use `yield return b;` from the loop (extract this loop to a new method, an _iterator block_). – Jeppe Stig Nielsen Jul 24 '13 at 10:49
  • Why would you want to do that? Linq is designed to query why would you manually build a list like that when Linq does it for you – Mark Homer Jul 25 '13 at 15:52
  • Perhaps you have a good reason you simply left out, but why would you not simply change `books = books.Concat(new[] {b});` to `books = books == null ? new[]{b} : books.Concat(new[] {b});`. Still I question why your `books` variable is an `IEnumerable` in the first place? Do you not own it, i.e. did you get it like that from somewhere else in your code? – AnorZaken Apr 04 '16 at 02:02

5 Answers5

111

It seams all you want to do is filter your context.Books by some criteria.

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

If you still need the empty IEnumerable you can just call Enumerable.Empty():

IEnumerable<Book> books = Enumerable.Empty<Book>();
Rodrigo López
  • 4,039
  • 1
  • 19
  • 26
28
IEnumerable<Book> books = new List<Book>();
chris.ellis
  • 883
  • 6
  • 10
4

Personally I'd just go with:

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

rather than using a List.

Matthew Watson
  • 104,400
  • 10
  • 158
  • 276
  • 1
    Although I would still use `Enumerable.Empty` rather than this, because it avoids creating new array instances, this is still better than creating a `List` as per the accepted answer because there is an optimization in .net that caches Enumerators for zero length arrays! – AnorZaken Apr 04 '16 at 01:34
  • @AnorZaken I do agree that `Enumberable.Empty` would be better (since it's more descriptive), but note that it does still (lazily) create an empty array. – Matthew Watson Apr 04 '16 at 08:21
  • 1
    Yes but it does so only once for each type T, using the type-system and JIT to make it lazy and cached (generic static readonly field). So `Enumerable.Empty` still comes out on top. (We don't know how many times that line there will be called - maybe a 1000 times per second, only OP knows.) – AnorZaken Apr 05 '16 at 14:51
4

This is what you are trying to do:

IEnumerable<Book> books = Enumerable.Empty<Book>();
books = books.Concat(context.Books.AsEnumerable().Where(b => someCondition));

Alternatively you can do this if you like to start from null:

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

...although I have several question as to why you want / need to do things this way.

AnorZaken
  • 1,916
  • 1
  • 22
  • 34
1

You need create books as a IEnumerable empty object like List, but need remember to call, after loop, ToList() on books. For example:

        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();
darthkurak
  • 157
  • 1
  • 2
  • 12