C# LINQ SelectMany
last modified October 16, 2026
In this article we show how to flatten sequences into a single sequence with
the LINQ SelectMany method.
Language-Integrated Query (LINQ) is a domain-specific language for querying data from various data sources, including arrays, lists, XML files, or databases.
The SelectMany method projects each element of a sequence to a
sequence and flattens the resulting sequences into one sequence. While
Select produces one output element for each input element,
SelectMany can produce zero, one, or many.
C# LINQ SelectMany array of arrays
The first example is a simple program which uses the SelectMany
method.
int[][] vals =
[
[1, 2, 3],
[4],
[5, 6, 6, 2, 7, 8]
];
var res = vals.SelectMany(a => a).OrderBy(e => e);
Console.WriteLine(string.Join(", ", res));
In the program, we have a jagged array. With the SelectMany
method, we flatten it into a single sequence of values. The values are also
ordered.
$ dotnet run 1, 2, 2, 3, 4, 5, 6, 6, 7, 8
C# LINQ SelectMany Distinct
The Distinct method is used to get unique values.
List<List<int>> vals =
[
[1, 2, 3, 3],
[4],
[5, 6, 6, 7, 7]
];
var res = vals.SelectMany(list => list)
.Distinct()
.OrderByDescending(e => e);
Console.WriteLine(string.Join(", ", res));
In the program, we flatten all integers from a list of lists into a single sequence. We pick up only unique values and order them in descending order.
$ dotnet run 7, 6, 5, 4, 3, 2, 1
C# LINQ SelectMany string list
A string is a sequence of characters. In the next example, we apply the
SelectMany method on a list of strings.
List<string> words = ["осторожность", "собака", "облако", "чашка"];
var letters = words.SelectMany(e => e);
Console.WriteLine(string.Join(",", letters));
var unique = words.SelectMany(e => e).Distinct().Order();
Console.WriteLine(string.Join("", unique));
We define a list of Russian words. The SelectMany method cuts the
words into letters and forms a single sequence from them. In the second query,
we get the unique letters in alphabetical order.
$ dotnet run о,с,т,о,р,о,ж,н,о,с,т,ь,с,о,б,а,к,а,о,б,л,а,к,о,ч,а,ш,к,а абжклнорстчшь
C# LINQ SelectMany on record property
The next example applies the SelectMany method on a property of
records.
List<User> users =
[
new("John", "Doe", ["red", "blue"]),
new("Roger", "Roe", ["black", "yellow"]),
new("Jerry", "Dane", ["blue", "orange", "white"]),
new("Thomas", "Green", ["brown"])
];
List<string> res = users.SelectMany(e => e.Colours).ToList();
Console.WriteLine(string.Join(",", res));
record User(string FirstName, string LastName, List<string> Colours);
We have a list of users, who have their favourite colours specified. The colours are defined as a list of strings inside a record type.
List<string> res = users.SelectMany(e => e.Colours).ToList();
The flattening operation is applied on the Colours property of the
records.
$ dotnet run red,blue,black,yellow,blue,orange,white,brown
C# LINQ SelectMany with result selector
An overload of SelectMany takes a second function, the result
selector. It receives both the parent element and the inner element, so we do
not lose the information about where each inner element came from.
List<User> users =
[
new("John", "Doe", ["red", "blue"]),
new("Roger", "Roe", ["black", "yellow"]),
new("Jerry", "Dane", ["blue", "orange", "white"])
];
var pairs = users.SelectMany(u => u.Colours,
(u, colour) => $"{u.FirstName} likes {colour}");
foreach (var pair in pairs)
{
Console.WriteLine(pair);
}
record User(string FirstName, string LastName, List<string> Colours);
For each colour, we create a string that also contains the name of the user.
$ dotnet run John likes red John likes blue Roger likes black Roger likes yellow Jerry likes blue Jerry likes orange Jerry likes white
C# LINQ SelectMany query syntax
In the query syntax, SelectMany corresponds to two
from clauses.
List<User> users =
[
new("John", "Doe", ["red", "blue"]),
new("Roger", "Roe", ["black", "yellow"]),
new("Jerry", "Dane", ["blue", "orange", "white"])
];
var res = from u in users
from colour in u.Colours
where colour == "blue"
select u.FirstName;
Console.WriteLine(string.Join(", ", res));
char[] letters = ['a', 'b', 'c'];
int[] digits = [1, 2];
var product = from l in letters
from d in digits
select $"{l}{d}";
Console.WriteLine(string.Join(" ", product));
record User(string FirstName, string LastName, List<string> Colours);
In the first query, we find the users who like blue colour. The second query creates a Cartesian product of letters and digits; the inner sequence does not have to depend on the outer element.
$ dotnet run John, Jerry a1 a2 b1 b2 c1 c2
C# LINQ Select vs SelectMany
If we use Select instead of SelectMany, we get a
sequence of lists, which we have to flatten ourselves.
List<User> users =
[
new("John", "Doe", ["red", "blue"]),
new("Roger", "Roe", ["black", "yellow"]),
new("Jerry", "Dane", ["blue", "orange", "white"]),
new("Thomas", "Green", ["brown"])
];
IEnumerable<List<string>> res = users.Select(e => e.Colours);
var colours = new List<string>();
foreach (var cols in res)
{
colours.AddRange(cols);
}
Console.WriteLine(string.Join(",", colours));
record User(string FirstName, string LastName, List<string> Colours);
The Select method returns an
IEnumerable<List<string>>. We go over the lists and
add their elements to a single list with AddRange. The
SelectMany method does the same in one call.
$ dotnet run red,blue,black,yellow,blue,orange,white,brown
Source
In this article we have presented the LINQ SelectMany method.
Author
List all C# tutorials.