Reputation: 2533
In the following code:
var cats = new List<string>() {"cat1", "cat2"};
var dogs = new List<string>() {"dog1", "dog2"};
var animals = new List<Animal>();
animals = (cats.Select(x => new Animal() {Type = "Cat", Name = x}).ToList().AddRange(
dogs.Select(x => new Animal() {Type = "Dog", Name = x}).ToList())).ToList();
Calling the ToList() at the end is an error, because AddRange() returns void. This doesn't seem right nowadays when using Linq type queries.
I found I could change it to .Union()
or .Concat()
to fix the issue, but shouldn't AddRange()
be updated, or is there a reason for it returning void?
Upvotes: 4
Views: 2128
Reputation: 10427
In your case, it is better to use Enumerable.Concat
:
animals = cats.Select(x => new Animal() {Type = "Cat", Name = x})
.Concat(dogs.Select(x => new Animal() {Type = "Dog", Name = x})).ToList();
Upvotes: 3
Reputation: 64467
AddRange
is a method on List<T>
that pre-dates LINQ. It mutates the current list in situ and so doesn't need to return it (nor does it follow the fluent syntax style you find a lot these days). List<T>
is not immutable, so mutating method calls are fine.
There are linq methods that can join lists together (as you've noted in the question). I would tend to not have mutating actions embedded in a linq method chain as it goes against the general idea that linq is just a query / projection set-up and doesn't "update" things.
Upvotes: 3
Reputation: 77285
AddRange
changes the underlying List object. No LinQ method does that. So it's fundamentally different and should not be used in a LinQ concatination. It's return value of void
reflects that.
Upvotes: 6
Reputation: 2064
You've answered your own question. If you want distinct values from the two lists use Union, if you want to just join the two lists use Concat. Once the two enumerable have been joined you can call ToList().
AddRange is a method on the List its self and isn't anything to do with LINQ.
Upvotes: 5