首頁 >後端開發 >C++ >如何有效,安全地在C#中隨機地列出一個通用列表?

如何有效,安全地在C#中隨機地列出一個通用列表?

Mary-Kate Olsen
Mary-Kate Olsen原創
2025-02-03 07:50:11188瀏覽

How Can I Randomly Shuffle a Generic List in C# Efficiently and Safely?

C#泛型列表的隨機排序

對泛型列表(例如數字列表)進行隨機排序是編程中的一項常見任務。在C#中,有多種方法可以使用內置方法、擴展方法甚至第三方庫來實現此目的。了解最佳方法和局限性對於獲得最佳性能和正確性至關重要。

Fisher-Yates洗牌擴展方法

最常用的方法之一是使用Fisher-Yates洗牌算法。此方法通過重複交換具有隨機索引的元素來隨機打亂IList的元素。下面的代碼塊演示了一個實現Fisher-Yates算法的擴展方法:

<code class="language-csharp">private static Random rng = new Random();

public static void Shuffle<T>(this IList<T> list)
{
    int n = list.Count;
    while (n > 1)
    {
        n--;
        int k = rng.Next(n + 1);
        T value = list[k];
        list[k] = list[n];
        list[n] = value;
    }
}</code>

要使用此擴展方法,只需對IList調用Shuffle()即可。例如:

<code class="language-csharp">List<Product> products = GetProducts();
products.Shuffle();</code>

使用System.Security.Cryptography提高隨機性

雖然System.Random很方便,但它並不總是能提供足夠的隨機性。如果需要更高質量的隨機性,System.Security.Cryptography庫提供了一個更安全的隨機數生成器:

<code class="language-csharp">using System.Security.Cryptography;
...
public static void Shuffle<T>(this IList<T> list)
{
    using (RNGCryptoServiceProvider provider = new RNGCryptoServiceProvider())
    {
        int n = list.Count;
        while (n > 1)
        {
            byte[] box = new byte[1];
            do provider.GetBytes(box);
            while (!(box[0] < (byte)((double)uint.MaxValue / uint.MaxValue * n)));
            int k = (int)(box[0] % n);
            T value = list[k];
            list[k] = list[n - 1];
            list[n - 1] = value;
        }
    }
}</code>

性能考慮和線程安全的重要性

在第一個示例中使用的System.Random類不是線程安全的。這意味著如果多個線程同時嘗試訪問同一個System.Random實例,則可能會出現不正確的結果。為了解決這個問題,ThreadSafeRandom類通過使用線程局部隨機數生成器提供了一種線程安全的解決方案。使用ThreadSafeRandom的修改後的Shuffle()擴展方法確保了在多線程環境中的正確性。

結論

在隨機化泛型列表時,開發人員可以在使用System.Random(為了方便)或System.Security.Cryptography(為了更好的隨機性)的Fisher-Yates洗牌擴展方法之間進行選擇。此外,ThreadSafeRandom類有助於確保在多線程應用程序中的線程安全。具體方法取決於所需的隨機性和性能考慮。

以上是如何有效,安全地在C#中隨機地列出一個通用列表?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn