How to Shuffle a List in C#: From Beginner to Confident User
\n\nImagine a situation: you are writing a quiz program, and the questions should appear in random order. Or maybe you are making a prize draw application where each participant gets a random number. Or perhaps you just want a music playlist to play in random order instead of alphabetically. In all these cases, you face the same task: how to shuffle a list (List<T>) in C#?
\n\nThis question is so popular that on Stack Overflow it has gathered thousands of views and hundreds of answers. And this is not surprising — although the task seems simple, it has its pitfalls. In this article, we will cover three of the most popular ways to randomize a list in C#, from the simplest to the most efficient. You will learn how each method works, when to use it, and importantly, how to avoid common mistakes.
\n\nWhy Can't You Just Sort Randomly?
\n\nThe first thing that comes to a beginner's mind: "Let me just sort the list randomly!" It looks something like this:
\n\nList<string> myList = new List<string> { "Apple", "Banana", "Cherry", "Melon" };\nRandom rnd = new Random();\nvar shuffled = myList.OrderBy(item => rnd.Next()).ToList();\n\n\nThe code works. But only at first glance. The problem is that Random.Next() is called once for each element, and the comparison is based on a single random number. This does not guarantee a uniform distribution. Moreover, this approach can lead to bias — some elements will more often end up at the beginning or end of the list. For serious applications (e.g., scientific calculations or games), this is unacceptable.
But don't rush to discard this method! For simple tasks where precision is not critical, it will suffice. Just remember its limitations.
\n\nMethod #1: The Fisher-Yates Algorithm (aka Knuth Shuffle) — The Gold Standard
\n\nIf you want to do it right the first time, use the Fisher-Yates algorithm. This is a classic method for shuffling an array or list, used in programming since 1938. It runs in O(n) time and uses O(1) extra memory — meaning it is very fast and efficient.
\n\nHere is how it looks in C#:
\n\nusing System;\nusing System.Collections.Generic;\n\npublic static class ListExtensions\n{\n private static readonly Random rng = new Random();\n\n public static void Shuffle<T>(this IList<T> list)\n {\n int n = list.Count;\n while (n > 1)\n {\n n--;\n int k = rng.Next(n + 1);\n T value = list[k];\n list[k] = list[n];\n list[n] = value;\n }\n }\n}\n\n\nHow does it work?
\n- \n
- We start from the last element of the list. \n
- Choose a random index from 0 to the current position. \n
- Swap the element at the current position with the element at the random index. \n
- Move to the previous element and repeat until we reach the beginning. \n
Why is it the best choice?
\n- \n
- Uniformity: Every permutation of elements is equally likely. \n
- Efficiency: One pass through the list, no extra operations. \n
- In-place: Does not create new lists, saving memory. \n
- Versatility: Works with any
IList<T>type, including arrays. \n
Usage is simple:
\n\nList<int> numbers = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };\nnumbers.Shuffle();\n// Now numbers is in random order\n\n\nNote: we declared