I am trying to use the Fisher-Yates algorithm to shuffle a stack of elements. I’m having trouble passing in the stack by reference. The code below gives the error “Iterators cannot have ref or out parameters”. How do I get the algorithm to act on the actual stack that gets passed in?
Thanks.
Code is below.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
public static class Doshuffle
{
public static IEnumerable<T> Shuffle<T>(ref Stack<T> source)
{
Random rng = new Random();
T[] elements = source.ToArray();
source.Clear();
// Note i > 0 to avoid final pointless iteration
for (int i = elements.Length - 1; i > 0; i--)
{
// Swap element "i" with a random earlier element it (or itself)
int swapIndex = rng.Next(i + 1);
T tmp = elements[i];
elements[i] = elements[swapIndex];
elements[swapIndex] = tmp;
}
// Lazily yield (avoiding aliasing issues etc)
foreach (T element in elements)
{
source.Push(element);
yield return element;
}
}
}
}
You do not need a
refparameter here sinceStack<T>is a reference type and you are not trying to re-assign the reference itself.References are by default passed by value but that value (the reference) points to the same object on the heap, in other words you have two references pointing to the same object which is fine – all operations will be executed on the original
Stack<T>object.Edit:
In light of your comment I suggest you redesign to not modify the original
Stack<T>which is troublesome to begin with:Now you can just use it like this:
Also be careful with your use of
Random– you might want to pass it in. At this point you can use Jon Skeet’s Shuffle implementation instead of your own – it’s better to reuse than reinvent.Final Edit:
It looks like you just want to shuffle your
Stack<T>in place -use an extension method instead:Now you can just do: