C# 如何实现扩展方法像列表的反转一样洗牌而不返回?

C# 如何实现扩展方法像列表的反转一样洗牌而不返回?,c#,list,extension-methods,reverse,shuffle,C#,List,Extension Methods,Reverse,Shuffle,到目前为止,我已经有了如下的洗牌代码 public static IList<T> Shuffle<T>(this IList<T> list) { var rnd = new Random(); return list.OrderBy(element => rnd.Next()); } 我希望能够像这样使用它 list.Shuffle(); // like list.Reverse();

到目前为止,我已经有了如下的洗牌代码

    public static IList<T> Shuffle<T>(this IList<T> list)
    {
        var rnd = new Random();
        return list.OrderBy(element => rnd.Next());
    }
我希望能够像这样使用它

    list.Shuffle(); // like list.Reverse();
所以基本上我想通过引用来洗牌

我尝试了以下代码

    public static void Shuffle<T>(this ref IList<T> list)
    {
        var rnd = new Random();
        list.OrderBy(element => rnd.Next());
    }
但它不起作用


非常感谢您的帮助

这是我很久以前写的。可能值得检查它是否适用于链接的算法。众所周知,这类事情很容易出错

    //Fisher-Yates_shuffle http://en.wikipedia.org/wiki/Fisher-Yates_shuffle
    private static readonly ThreadLocal<Random> RandomThreadLocal =
        new ThreadLocal<Random>(() => new Random());
    public static void Shuffle<T>(this IList<T> list, int seed = -1)
    {
        var r = seed >= 0 ? new Random(seed) : RandomThreadLocal.Value;
        var len = list.Count;
        for (var i = len - 1; i >= 1; --i)
        {
            var j = r.Next(i);
            var tmp = list[i];
            list[i] = list[j];
            list[j] = tmp;
        }
    }
根据下面的评论,可以重载以获得更大的灵活性:

    private static readonly ThreadLocal<Random> RandomThreadLocal =
        new ThreadLocal<Random>(() => new Random());
    public static void Shuffle<T>(this IList<T> list, int seed)
    {
        list.Shuffle(new Random(seed));
    }

    public static void Shuffle<T>(this IList<T> list)
    {
        list.Shuffle(null);
    }

    public static void Shuffle<T>(this IList<T> list, Random rand)
    {
        var r = rand ?? RandomThreadLocal.Value;

        var len = list.Count;
        for (var i = len - 1; i >= 1; --i)
        {
            var j = r.Next(i);
            var tmp = list[i];
            list[i] = list[j];
            list[j] = tmp;
        }
    }

这是我很久以前写的。可能值得检查它是否适用于链接的算法。众所周知,这类事情很容易出错

    //Fisher-Yates_shuffle http://en.wikipedia.org/wiki/Fisher-Yates_shuffle
    private static readonly ThreadLocal<Random> RandomThreadLocal =
        new ThreadLocal<Random>(() => new Random());
    public static void Shuffle<T>(this IList<T> list, int seed = -1)
    {
        var r = seed >= 0 ? new Random(seed) : RandomThreadLocal.Value;
        var len = list.Count;
        for (var i = len - 1; i >= 1; --i)
        {
            var j = r.Next(i);
            var tmp = list[i];
            list[i] = list[j];
            list[j] = tmp;
        }
    }
根据下面的评论,可以重载以获得更大的灵活性:

    private static readonly ThreadLocal<Random> RandomThreadLocal =
        new ThreadLocal<Random>(() => new Random());
    public static void Shuffle<T>(this IList<T> list, int seed)
    {
        list.Shuffle(new Random(seed));
    }

    public static void Shuffle<T>(this IList<T> list)
    {
        list.Shuffle(null);
    }

    public static void Shuffle<T>(this IList<T> list, Random rand)
    {
        var r = rand ?? RandomThreadLocal.Value;

        var len = list.Count;
        for (var i = len - 1; i >= 1; --i)
        {
            var j = r.Next(i);
            var tmp = list[i];
            list[i] = list[j];
            list[j] = tmp;
        }
    }

我还喜欢在现有随机实例中传递的其他实例之外提供一个重载。还值得注意的是,该算法也比OP中的算法更有效。它是开的,而不是开*logn。上面的Shuffle算法实现有一个错误。Random.Nextint maxValue是一个独占的上限,但您希望它包含在内。只需替换var j=r.Nexti;变量j=r.Nexti+1;还有你的好去处。@Keith。。。干得好,让我信守诺言。确实有点错误!我还喜欢在现有随机实例中传递的其他实例之外提供一个重载。还值得注意的是,该算法也比OP中的算法更有效。它是开的,而不是开*logn。上面的Shuffle算法实现有一个错误。Random.Nextint maxValue是一个独占的上限,但您希望它包含在内。只需替换var j=r.Nexti;变量j=r.Nexti+1;还有你的好去处。@Keith。。。干得好,让我信守诺言。确实有点错误!