Using lambda expression in place of IComparer argument
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
In C#, methods like Array.Sort() and List.Sort() accept an IComparer<T> argument for custom sorting. Instead of creating a separate class that implements IComparer<T>, you can pass a lambda expression using Comparer<T>.Create(). This converts a two-parameter lambda into a valid IComparer<T> instance, making sort customization a one-liner instead of a multi-class affair.
The Traditional IComparer Approach
Without lambdas, custom sorting requires a dedicated class:
This works but creates boilerplate for every custom sort order.
Using Comparer<T>.Create with Lambda
Comparer<T>.Create() takes a Comparison<T> delegate (a lambda with two parameters) and wraps it in an IComparer<T>:
Direct Comparison<T> Delegate
Some overloads accept a Comparison<T> delegate directly, so you can skip Comparer<T>.Create:
The difference: Sort(Comparison<T>) takes a delegate directly, while methods requiring IComparer<T> need Comparer<T>.Create().
Practical Examples
Sort Objects by Multiple Fields
Descending Sort
Case-Insensitive String Sort
SortedSet and SortedDictionary
Collections that require IComparer<T> in their constructor need Comparer<T>.Create:
LINQ OrderBy (No IComparer Needed)
LINQ's OrderBy and ThenBy use key selectors, which are even simpler than comparison lambdas:
When to Use Which
| Scenario | Approach |
List.Sort() or Array.Sort() | Lambda directly: (x, y) => ... |
Constructor requiring IComparer<T> | Comparer<T>.Create((x, y) => ...) |
| Complex reusable comparison logic | Separate IComparer<T> class |
| LINQ sorting | OrderBy(x => x.Property) |
Common Pitfalls
- Inconsistent comparison: A comparer must be consistent — if
Compare(a, b) < 0, thenCompare(b, a) > 0. An inconsistent lambda causesArgumentExceptionor unpredictable sort order. - Forgetting null handling: If the collection can contain nulls, the lambda must handle
nullarguments.x.CompareTo(y)throwsNullReferenceExceptionifxis null. - Using
Comparer<T>.CreatewhenComparison<T>is accepted:List.Sort()andArray.Sort()acceptComparison<T>directly — no need forComparer<T>.Create. UseCreateonly when the API specifically requiresIComparer<T>. - Subtraction instead of CompareTo for integers:
(x, y) => x - yworks for small values but overflows for extreme int values (e.g.,int.MinValue - 1). Always usex.CompareTo(y). - Mutating state in the comparer lambda: The comparison function should be pure — no side effects. Sorting algorithms call the comparer unpredictably many times, and side effects lead to bugs.
Summary
- Use
Comparer<T>.Create((x, y) => ...)to create anIComparer<T>from a lambda expression List.Sort()andArray.Sort()acceptComparison<T>lambdas directly withoutCreate- For
SortedSet,SortedDictionary, and other constructors requiringIComparer<T>, useComparer<T>.Create - Always use
.CompareTo()instead of subtraction to avoid integer overflow - LINQ's
OrderBy(x => x.Property)is simpler than comparison lambdas when you just need to sort by a key

