Non-recursive solution, works on any IEnumerables (not just lists) without solidifying them:
public static IEnumerable> Permutations(
this IEnumerable> source)
{
// Check source non-null, non-empty?
var enumerables = source.ToArray();
Stack> fe = new Stack>();
fe.Push(enumerables[0].GetEnumerator());
while (fe.Count > 0)
{
if (fe.Peek().MoveNext())
{
if (fe.Count == enumerables.Length)
yield return new Stack(fe.Select(e => e.Current));
else
fe.Push(enumerables[fe.Count].GetEnumerator());
}
else
{
fe.Pop().Dispose();
}
}
}