Select and SelectMany in C#: Which to Choose for Speed?

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Select and SelectMany in C#: What's the Difference and How Does It Affect Speed?



If you've ever written LINQ queries in C#, you've likely encountered two similar but very different methods: Select and SelectMany. At first glance, both "select something" from a collection. But the devil, as always, is in the details. Choosing the wrong one can turn your fast code into a sluggish mess, while the right choice can make it elegant and lightning-fast.



In this article, we won't just cover the theory. We'll conduct a real performance test, look at the internal workings of both methods, and give you a clear algorithm: when to use Select and when to use SelectMany. Ready? Let's go!



Quick Primer: What Are Select and SelectMany?



First, the basics. Imagine you have a list of students (List<Student>), and each student has a list of grades (List<int>).



Select is a "one-to-one" projection. For each element in the source collection, you get exactly one element as output. If you have 10 students, Select will return a collection of 10 elements.



  • Example: Get the names of all students.
  • Signature: IEnumerable<TResult> Select<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector)


SelectMany is a "one-to-many" projection followed by flattening. Each element in the source collection can produce multiple output elements, and they are all merged into a single flat list.



  • Example: Get all grades of all students (a single flat list of numbers).
  • Signature: IEnumerable<TResult> SelectMany<TSource, TCollection, TResult>(this IEnumerable<TSource> source, Func<TSource, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> resultSelector)


The difference seems obvious. But where's the catch? The catch is in how these methods work under the hood and how beginners often confuse them.



The Main Difference: Output Data Shape



Let's solidify this with a code example. Here's our model class:



public class Student{    public string Name { get; set; }    public List<int> Grades { get; set; } = new List<int>();}

// Creating datavar students = new List<Student>{ new Student { Name = "Anna", Grades = new List<int>{ 5, 4, 5 } }, new Student { Name = "Boris", Grades = new List<int>{ 3, 4 } }, new Student { Name = "Vika", Grades = new List<int>{ 5, 5, 5, 4 } }};


Example 1: Using Select (incorrectly)



// We want to get all grades. But Select returns a collection of collections!var allGradesNested = students.Select(s => s.Grades);// Type: IEnumerable<List<int>> — three lists inside!

foreach (var gradeList in allGradesNested){ foreach (var grade in gradeList) { Console.Write(grade + " "); // We have to use a nested loop }}// Output: 5 4 5 3 4 5 5 5 4


This works, but it's inconvenient. You get a nested structure that needs additional flattening.



Example 2: Using SelectMany (correctly)



// SelectMany does all the work for us: it takes the inner collections and flattens themvar allGradesFlat = students.SelectMany(s => s.Grades);// Type: IEnumerable<int> — a single flat list of numbers!

foreach (var grade in allGradesFlat){ Console.Write(grade + " "); // No nested loops!}// Output: 5 4 5 3 4 5 5 5 4


Can you feel the differenc

Blogs

Book Recommendations