Use the modern version of the Fisher-Yates shuffle
From Wikipedia: The Fisher–Yates shuffle is an algorithm for generating a random permutation of a finite sequence — in plain terms, the algorithm shuffles the sequence
The following is implemented as extension function, so you can use it in a concatenation of LINQ statements:
private static readonly Random rnd = new Random();
public static IEnumerable<TSource> Shuffle<TSource>(this IEnumerable<TSource> source)
{
// TODO: exception if source equals null
// copy the source items to a new List, we don't want to shuffle the input, do we?
List<TSource> sourceItems = source.ToList();
int lastIndex = sourceItems.Count-1;
for (int i = 0; i < lastIndex; ++i)
{
// pick an index number on or after i
// if the picked number equals i, then do not shuffle element [i]
int j = rnd.Next(i, sourceItems.Count);
if (i != j)
{ // swap:
var tmp = sourceItems[i];
sourceItems[i] = sourceItems[j];
sourceItems[j] = tmp;
}
// yield return the next element of the shuffled sequence
yield return sourceItems[i];
}
}
usage:
List<MyClass> input = ...
IEnumerable<MyClass> output = input.Shuffle();
Note that the input is not shuffled.
The nice thing is, that if you only want a few outputs, no more items are shuffled then necessarry. The following will only take 3 elements from your original list:
var output = Enumerable.Range(0, 10)
.Shuffle()
.Take(3)
.ToList();
output is 3 distinct random numbers between 0 and 9