100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
C#

LINQ to Objects

LINQ to Objects is the flavor of LINQ that runs entirely in memory against IEnumerable<T> collections like arrays, List<T>, and Dictionary<T>, using compiled delegates rather than translated queries.

FoundationsBeginner8 min readJul 10, 2026
Analogies

LINQ to Objects

LINQ to Objects refers to using LINQ's standard query operators directly against in-memory collections that implement IEnumerable<T> — arrays, List<T>, Dictionary<TKey,TValue>, HashSet<T>, and so on. Unlike LINQ to Entities (used by Entity Framework Core), there's no query translation happening: the Where and Select methods you call compile down to ordinary C# delegates (Func<T,bool>, Func<T,TResult>) that execute directly against the objects already sitting in your process's memory.

🏏

Cricket analogy: Like a domestic net session where a batter faces throwdowns from a coach standing right there — no broadcast delay, no translation — LINQ to Objects runs its Where and Select delegates directly against an in-memory List<T>, with no translation step to another query language.

How It Works Under the Hood

Most LINQ to Objects operators — Where, Select, Skip, Take — are implemented as C# iterator methods using yield return. This means they don't run immediately: calling numbers.Where(n => n > 10) just builds an iterator object. The actual predicate is only evaluated element by element when something calls MoveNext() on the resulting enumerator, typically through a foreach loop or a call like ToList(). This lazy, pull-based model is what makes LINQ to Objects memory-efficient for large in-memory sequences.

🏏

Cricket analogy: Like a bowler's run-up that only actually happens ball by ball when the umpire signals play, LINQ to Objects' Where uses a C# iterator with yield return, so each element is only tested against the Func<T,bool> predicate when MoveNext() is actually called during enumeration.

Common Operators in Practice

In everyday code, LINQ to Objects queries typically chain a handful of operators: Where to filter, Select to project into a new shape, GroupBy to bucket elements by a key, OrderBy/OrderByDescending to sort, and Aggregate or Sum/Count/Max to reduce a sequence to a single value. Because these are all extension methods on IEnumerable<T>, they work identically on an array, a List<T>, a Dictionary<T>.Values, or any custom type that implements IEnumerable<T>.

🏏

Cricket analogy: Like a scorecard that groups deliveries by bowler (GroupBy), filters to only wickets (Where), and totals runs conceded (Aggregate), LINQ to Objects chains balls.Where(b => b.IsWicket).GroupBy(b => b.Bowler) directly over a List<Ball> in memory.

csharp
var transactions = new List<Transaction>
{
    new("Groceries", 84.20m), new("Rent", 1500m),
    new("Groceries", 42.10m), new("Utilities", 96.50m)
};

var totalsByCategory = transactions
    .Where(t => t.Amount > 50)
    .GroupBy(t => t.Category)
    .Select(g => new { Category = g.Key, Total = g.Sum(t => t.Amount) })
    .OrderByDescending(g => g.Total);

foreach (var g in totalsByCategory)
    Console.WriteLine($"{g.Category}: {g.Total:C}");

LINQ to Objects works on any type implementing IEnumerable<T> — this includes Dictionary<TKey,TValue> (iterating KeyValuePair<TKey,TValue>), HashSet<T>, Stack<T>, Queue<T>, and even a custom class that implements IEnumerable<T> with its own iterator logic.

  • LINQ to Objects operates on in-memory IEnumerable<T> collections: arrays, List<T>, Dictionary<T>, HashSet<T>, etc.
  • It uses compiled Func<T,bool> and Func<T,TResult> delegates, not expression trees translated to another language.
  • Most operators (Where, Select) are implemented as C# iterators using yield return, executing lazily.
  • Predicates only run when the sequence is actually enumerated — via foreach, ToList(), or similar.
  • Common chains combine Where, Select, GroupBy, OrderBy, and Aggregate/Sum/Count to transform and reduce data.
  • Because it's all in-process, LINQ to Objects requires the full collection to already be in memory.

Practice what you learned

Was this page helpful?

Topics covered

#LINQStudyNotes#MicrosoftTechnologies#LINQToObjects#LINQ#Objects#Works#Under#OOP#StudyNotes#SkillVeris