C
C#3y ago
surwren

Where does LinQ store its IEnumerable selections?

Say I have the following sample code
char[] upperCase0 = { 'A', 'B', 'C', 'D' };
string[] upperCase = { "A", "B", "C", "D" };
string[] lowerCase = { "c","b","a"};

var iterB = from up0 in upperCase0
from up in upperCase
from low in lowerCase
where Char.ToLower(up0).ToString() == low && low== up.ToLower()
select new { up0, up, low };
char[] upperCase0 = { 'A', 'B', 'C', 'D' };
string[] upperCase = { "A", "B", "C", "D" };
string[] lowerCase = { "c","b","a"};

var iterB = from up0 in upperCase0
from up in upperCase
from low in lowerCase
where Char.ToLower(up0).ToString() == low && low== up.ToLower()
select new { up0, up, low };
List<Person> personList = new List<Person>()
{
new Person() { Name="John", Age=32, Kids=2, Gender='M'},
new Person() { Name="Ana", Age=28, Kids=3, Gender='F'},
new Person() { Name="Mary", Age=42, Kids=2, Gender='F'},
new Person() { Name="Jason", Age=33, Kids=1, Gender='M'},
new Person() { Name="Mike", Age=22, Kids=0, Gender='M'}
};

var iterC = personList
.Where(p => p.Age > 30)
.OrderByDescending(p => p.Age)
.Select(p => p.Name);
List<Person> personList = new List<Person>()
{
new Person() { Name="John", Age=32, Kids=2, Gender='M'},
new Person() { Name="Ana", Age=28, Kids=3, Gender='F'},
new Person() { Name="Mary", Age=42, Kids=2, Gender='F'},
new Person() { Name="Jason", Age=33, Kids=1, Gender='M'},
new Person() { Name="Mike", Age=22, Kids=0, Gender='M'}
};

var iterC = personList
.Where(p => p.Age > 30)
.OrderByDescending(p => p.Age)
.Select(p => p.Name);
Looking at the debugger, you can see that both iterB and iterC are null. Where exactly does LinQ store its queried data?
6 Replies
Thinker
Thinker3y ago
Linq doesn't materialize any data until you explicitly request it So it's not stored anywhere, it's generated on the fly when you iterate the IEnumerable. A Linq query is merely a hierarchy of instructions on how to transform an underlying enumerable. Essentially a Linq query returns a structure like this
Original collection: IEnumerable
Transformation: lambda expression
Get enumerator: Enumerate the original collection and apply the transformation onto every element
Original collection: IEnumerable
Transformation: lambda expression
Get enumerator: Enumerate the original collection and apply the transformation onto every element
That original collection may be an IEnumerable generated by another Linq query, thus you can chain them.
canton7
canton73y ago
Don't get too hung up on linq. Where for instance is essentially as simply as:
public static void Where<T>(this IEnumberable<T> input, Func<T, bool> predicate)
{
foreach (T item in input)
{
if (predicate(item))
{
yield return item;
}
}
}
public static void Where<T>(this IEnumberable<T> input, Func<T, bool> predicate)
{
foreach (T item in input)
{
if (predicate(item))
{
yield return item;
}
}
}
(There's some extra error handling and optimizations, but that's essentially it)
Thinker
Thinker3y ago
yep And note the special syntax here, yield again doesn't materialize anything until it's enumerated.
canton7
canton73y ago
Yeah, if you're not comfortable with yield return and enumerators/etc, I'd recommend getting comfortable with those before starting on linq
surwren
surwrenOP3y ago
I'm more worried about troubleshooting Because the data should be located somewhere in memory, otherwise how is my
foreach
foreach
method even outputting anything
canton7
canton73y ago
The next element in the sequence is generated on the next iteration of your foreach loop That's why I said to get comfortable with yield return first
Want results from more Discord servers?
Add your server