LINQ Cheatsheet
C#
16 views
Apr 2026
Filtering
// Where — filter elements
var adults = people.Where(p => p.Age >= 18);
// OfType — filter by type
var strings = objects.OfType<string>();
// Distinct / DistinctBy
var unique = nums.Distinct();
var uniquePeople = people.DistinctBy(p => p.Email); // .NET 6+
Projection
// Select — transform elements
var names = people.Select(p => p.Name);
var dtos = people.Select(p => new { p.Id, p.Name }); // anonymous type
// Select with index
var indexed = items.Select((item, i) => new { Index = i, Item = item });
// SelectMany — flatten nested collections
var allTags = posts.SelectMany(p => p.Tags);
var pairs = list1.SelectMany(a => list2, (a, b) => (a, b));
Ordering
var sorted = people.OrderBy(p => p.LastName)
.ThenBy(p => p.FirstName);
var reversed = people.OrderByDescending(p => p.Age)
.ThenByDescending(p => p.Name);
var shuffled = items.OrderBy(_ => Guid.NewGuid()); // random order
Grouping
// GroupBy — returns IGrouping<TKey, TElement>
var byDept = employees.GroupBy(e => e.Department);
foreach (var g in byDept) {
Console.WriteLine($"{g.Key}: {g.Count()} employees");
}
// Project the groups
var summary = employees
.GroupBy(e => e.Department)
.Select(g => new {
Dept = g.Key,
Count = g.Count(),
AvgSal = g.Average(e => e.Salary),
TopEarn = g.Max(e => e.Salary)
});
// ToLookup — like GroupBy but eagerly evaluated (good for repeated access)
var lookup = employees.ToLookup(e => e.Department);
var devs = lookup["Engineering"];
Joining
// Join — inner join
var result = orders.Join(
customers,
o => o.CustomerId,
c => c.Id,
(o, c) => new { o.Id, c.Name, o.Total }
);
// GroupJoin — left outer join
var withOrders = customers.GroupJoin(
orders,
c => c.Id,
o => o.CustomerId,
(c, ords) => new { c.Name, Orders = ords.ToList() }
);
// Zip — pair two sequences
var pairs = names.Zip(scores, (name, score) => $"{name}: {score}");
Aggregation
nums.Count();
nums.Count(x => x > 5); // conditional count
nums.Sum();
nums.Sum(x => x * 2);
nums.Min(); nums.Max();
nums.Average();
nums.Aggregate((acc, x) => acc + x); // custom fold
nums.Aggregate(0, (acc, x) => acc + x); // with seed
// MinBy / MaxBy (.NET 6+)
var youngest = people.MinBy(p => p.Age);
var richest = people.MaxBy(p => p.Salary);
Partitioning
// Pagination
var page = items.Skip(20).Take(10);
// Chunk (.NET 6+) — split into batches
foreach (var batch in items.Chunk(100)) {
ProcessBatch(batch);
}
// TakeWhile / SkipWhile
var head = nums.TakeWhile(x => x < 10);
var tail = nums.SkipWhile(x => x < 10);
Element Operations
nums.First(); // throws if empty
nums.First(x => x > 5);
nums.FirstOrDefault(); // returns default if empty
nums.FirstOrDefault(x => x > 5, -1); // .NET 6+ with fallback
nums.Single(); // throws if not exactly one
nums.SingleOrDefault();
nums.Last(); nums.LastOrDefault();
nums.ElementAt(3);
nums.ElementAtOrDefault(100);
Set Operations
a.Union(b); // a ∪ b (distinct)
a.Intersect(b); // a ∩ b
a.Except(b); // a − b
a.Concat(b); // a + b (with duplicates)
// By key (.NET 6+)
a.UnionBy(b, x => x.Id);
a.IntersectBy(b.Select(x => x.Id), x => x.Id);
a.ExceptBy(b.Select(x => x.Id), x => x.Id);
Quantifiers
nums.Any(); // has any element?
nums.Any(x => x > 100); // any match predicate?
nums.All(x => x > 0); // all match predicate?
nums.Contains(5); // contains value?
nums.SequenceEqual(other); // same elements in order?
Conversion
nums.ToList();
nums.ToArray();
nums.ToHashSet();
nums.ToDictionary(x => x.Id, x => x.Name);
nums.AsEnumerable(); // force IEnumerable (stop EF translation)
nums.AsQueryable();
Query Syntax vs Method Syntax
// Query syntax (SQL-like)
var result =
from p in people
where p.Age >= 18
orderby p.Name
select new { p.Name, p.Age };
// Method syntax (equivalent)
var result = people
.Where(p => p.Age >= 18)
.OrderBy(p => p.Name)
.Select(p => new { p.Name, p.Age });
// Mixed — join is easier in query syntax
var result =
from o in orders
join c in customers on o.CustomerId equals c.Id
where o.Total > 100
select new { c.Name, o.Total };