Enumerable.Distinct() / Take() / Skip()
| Since: | C# 3.0(2007) |
|---|
LINQ extension methods for removing duplicates, limiting results, and skipping elements from a sequence. These are commonly used for pagination.
Syntax
using System.Linq; // Removes duplicate elements. IEnumerable<T> unique = source.Distinct(); // Returns the first n elements. IEnumerable<T> top = source.Take(n); // Skips the first n elements and returns the rest. IEnumerable<T> rest = source.Skip(n); // Combines Take and Skip for pagination. IEnumerable<T> page = source.Skip((page - 1) * pageSize).Take(pageSize);
Method List
| Method | Description |
|---|---|
| Distinct() | Returns elements with duplicates removed. |
| DistinctBy(keySelector) | .NET 6 and later. Returns elements with duplicates removed based on the specified key. |
| Take(count) | Returns the specified number of elements from the start. |
| TakeLast(count) | Returns the specified number of elements from the end. |
| TakeWhile(predicate) | Returns elements from the start as long as the condition is true. |
| Skip(count) | Skips the specified number of elements from the start and returns the rest. |
| SkipLast(count) | Returns elements excluding the specified number from the end. |
| SkipWhile(predicate) | Skips elements from the start as long as the condition is true. |
| Chunk(size) | .NET 6 and later. Splits the sequence into batches (arrays) of the specified size. |
Sample Code
Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
List<int> numbers = new List<int> { 3, 1, 4, 1, 5, 9, 2, 6, 5, 3 };
// Distinct: removes duplicates (preserving first-occurrence order).
IEnumerable<int> unique = numbers.Distinct();
Console.WriteLine(string.Join(", ", unique)); // 3, 1, 4, 5, 9, 2, 6
// Take: gets the first 3 elements.
IEnumerable<int> top3 = numbers.Take(3);
Console.WriteLine(string.Join(", ", top3)); // 3, 1, 4
// Skip: skips the first 3 elements.
IEnumerable<int> rest = numbers.Skip(3);
Console.WriteLine(string.Join(", ", rest)); // 1, 5, 9, 2, 6, 5, 3
// Pagination: 3 items per page, get page 2.
int pageSize = 3;
int pageNum = 2;
IEnumerable<int> page = numbers.Skip((pageNum - 1) * pageSize).Take(pageSize);
Console.WriteLine(string.Join(", ", page)); // 1, 5, 9
// TakeWhile: takes elements from the start while the value is less than 5.
IEnumerable<int> tw = numbers.TakeWhile(n => n < 5);
Console.WriteLine(string.Join(", ", tw)); // 3, 1, 4, 1
// .NET 6 and later: DistinctBy removes duplicates by a specific key on objects.
var people = new List<(string Name, int Age)>
{
("Ayanami Rei", 14), ("Ikari Shinji", 14), ("Soryu Asuka", 14),
};
var byAge = people.DistinctBy(p => p.Age);
foreach (var p in byAge) Console.WriteLine(p.Name);
// .NET 6 and later: Chunk splits a list into batches.
var chunks = Enumerable.Range(1, 10).Chunk(3);
foreach (var chunk in chunks)
Console.WriteLine(string.Join(", ", chunk));
Run the following command:
dotnet run 3, 1, 4, 5, 9, 2, 6 3, 1, 4 1, 5, 9, 2, 6, 5, 3 1, 5, 9 3, 1, 4, 1 Ayanami Rei 1, 2, 3 4, 5, 6 7, 8, 9 10
Common Mistakes
Common Mistake: TakeWhile() Stops When the Condition First Becomes False
TakeWhile() evaluates elements from the start of the sequence and stops the moment the condition becomes false. Elements that appear after that point are never returned, even if they satisfy the condition. Use Where() when you want to filter across the entire sequence.
using System;
using System.Collections.Generic;
using System.Linq;
List<int> numbers = new List<int> { 1, 2, 6, 3, 4 };
// NG: TakeWhile stops at 6, so 3 and 4 are never returned
var ng = numbers.TakeWhile(n => n < 5);
Console.WriteLine(string.Join(", ", ng)); // 1, 2 (stops at 6)
Run the following command:
dotnet run 1, 2
The following example demonstrates this:
using System;
using System.Collections.Generic;
using System.Linq;
List<int> numbers = new List<int> { 1, 2, 6, 3, 4 };
// OK: Where filters across the entire sequence
var ok = numbers.Where(n => n < 5);
Console.WriteLine(string.Join(", ", ok)); // 1, 2, 3, 4
Run the following command:
dotnet run 1, 2, 3, 4
Notes
Distinct() compares reference types by reference equality and value types by value equality by default. To remove duplicates from custom objects, pass an IEqualityComparer<T>, or in .NET 6 and later, use DistinctBy() with a key selector for a more concise approach.
TakeWhile() and SkipWhile() evaluate from the start of the sequence, so once the condition becomes false, no further elements are processed — even if later elements would satisfy the condition. Use Where() if you want to filter across the entire sequence.
For generating sequences, Enumerable.Range() / Repeat() / Empty() is useful. For converting to a list or array, see Enumerable.ToList() / ToArray().
If you find any errors or copyright issues, please contact us.