Blog
Mert Özen's blog posts on software development, backend, frontend, and DevOps.
What Is LINQ? Query Syntax and Method Syntax in C#
What LINQ changes about the queries we used to write with loops, the C# 3.0 features behind it, how the compiler translates query syntax into method calls, when to pick which notation, and the first pitfalls.
LINQ Deferred Execution: When Does a Query Run? IEnumerable and IQueryable
Why a LINQ query runs when it is iterated rather than when it is defined, element-by-element streaming, immediate and buffering operators, the cost of multiple enumeration, and the IEnumerable versus IQueryable split through Func and expression trees.
Filtering and Sorting with LINQ: Where, OrderBy, ThenBy and Reverse
Where and its index overload, why a second OrderBy wipes out the first, multi-key sorting with ThenBy, stable OrderBy versus unstable List.Sort, culture-sensitive string ordering, and how Reverse differs from OrderByDescending.
Projection with LINQ: Select, SelectMany and Anonymous Types
One-to-one projection with Select and one-to-many with SelectMany; mapping to DTOs, keeping parent data with a result selector, the Cartesian product, the equality and with rules of anonymous types, and tuple versus record outside a method.
LINQ Element Operators: First, Last, Single, ElementAt and OrDefault
The First, Last, Single and ElementAt families and their OrDefault siblings; how 0 gets confused with 'not found' on value types, .NET 6's default value parameter and Index overloads, the difference in intent between First and Single, and nullable warnings.
LINQ Partitioning: Take, Skip, TakeWhile, Chunk and Take(Range)
Why TakeWhile is not a filter, correct paging with Skip and Take and the silent rule of ordering, how TakeLast/SkipLast read to the end, Take(Range) from .NET 6 versus array slicing, splitting into batches with Chunk, and exactly how much of the source the partitioning operators read.
LINQ Aggregation Operators: Count, Sum, Average, Min, Max, Aggregate and MinBy/MaxBy
Why Sum returns 0 and Max throws on an empty sequence, and the nullable selector and DefaultIfEmpty fixes. Count and .NET 6 TryGetNonEnumeratedCount, the return type of Average, the checked overflow of Sum, MinBy/MaxBy returning the element instead of the value, the three overloads of Aggregate, and how many times you enumerate the same query.
LINQ Grouping: GroupBy, IGrouping and ToLookup
How GroupBy runs deferred and ToLookup immediately, and what that does to the result. The key and elements of IGrouping, the documented group order, grouping and summarizing, the element and result selector overloads, group by into in query syntax, composite keys, how ToLookup handles a missing key, grouping with a comparer, and how GroupBy buffers its source.
LINQ Set Operations: Distinct, Union, Intersect, Except and DistinctBy
Where Distinct gets its equality from and why it removes nothing on a class without equality. How Union, Intersect and Except deduplicate the result, how they differ from Concat and Where, the documented order, comparing with a comparer, .NET 6 DistinctBy/UnionBy and IntersectBy/ExceptBy taking a list of keys, the CS0411 error, HashSet and deferred execution.
LINQ Join and GroupJoin: Inner Join, Composite Keys and the Left Join Pattern
How Join, as an inner join, drops unmatched rows and multiplies multiple matches, and its documented order. The direction of equals in query syntax and CS1937/CS1938, composite keys and CS1941, hierarchical results with GroupJoin, the left join pattern with GroupJoin + DefaultIfEmpty and its null trap, multiple joins, and how Join runs in n + m with a lookup.
LINQ Any, All, Contains, SequenceEqual and the Conversion Operators
Why All returns true on an empty sequence and why validation needs Any as well, how Any stops at the first element versus Count() > 0, Contains and record equality, SequenceEqual and the trap of records carrying collections, snapshots with ToList/ToArray/ToHashSet, duplicate keys in ToDictionary, and the difference between Cast and OfType.
Writing Your Own LINQ Operator: Extension Methods and yield return
Why a LINQ operator is just an extension method; writing lazy, streaming operators with yield return, separating argument validation from the iterator, immediate operators, finally when enumeration is abandoned early, an Expression-based operator for IQueryable and name clashes with the BCL.