I am having a hard time understanding why I am getting the results that I am.
I have two lists of strings:
var list1 = new List<String> {"item 1", "item 2"};
var list2 = new List<String> { "item 3", "item 4" };
Version 1 - Output: "item 2"
var item =
from x in (list1.Concat(list2))
where x.EndsWith("2")
select x;
Console.WriteLine(item.First());
Version 2 - Output: "i"
var item =
from x in (list1.Concat(list2))
where x.EndsWith("2")
select x.First();
Console.WriteLine(item.First());
Version 3 - Output: "System.Linq.Enumerable+WhereEnumerableIterator`1[System.String]"
var item =
from x in (list1.Concat(list2))
where x.EndsWith("2")
select x;
Console.WriteLine(item);
Given that version 2 outputs "i", I would expect version 3 to output "item 2". Why is this behavior occurring?
In version 3, select x
is returning a sequence of strings that match your critera; it just happens to be a sequence with one item in it.
Console.WriteLine
internally calls .ToString()
on whatever you pass into it. Since there is no meaningful string representation for IEnumerable<T>
, the default in .NET is to print the string name of the type.
Based on your wording, I think part of your confusion does come from a misunderstanding of why version 2 works the way it does. In version 2, select x.First()
is actually a bit of a quirk/coincidence, because a string is also an IEnumerable<char>
, so you can do LINQ operations on the string. .First()
returns the first element of that char
sequence, for each result that matches your criteria. So you're saying:
"For each element which matches my criteria, select the first character, and then return the sequence of all the first characters for the matches."
So in fact, item
in version 2 is an IEnumerable<char>
with one element in it. Calling Console.WriteLine()
on an IEnumerable<char>
will just print the chars in order. So you get "i".
(note: I see after I answered this, the question was edited to call .First()
both inside the projection and on the result, so the bit about passing IEnumerable<char>
to Console.WriteLine
isn't totally relevant anymore)
Keep in mind LINQ is pretty much about working with sets until you explicitly reduce them down. For example, Select
is simply a projection or transformation. It returns the same number of items that were passed to it, transformed. Where
reduces down the set, but it's still a set.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With