對泛型列表(例如數字列表)進行隨機排序是編程中的一項常見任務。在C#中,有多種方法可以使用內置方法、擴展方法甚至第三方庫來實現此目的。了解最佳方法和局限性對於獲得最佳性能和正確性至關重要。
最常用的方法之一是使用Fisher-Yates洗牌算法。此方法通過重複交換具有隨機索引的元素來隨機打亂IList
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; } }
要使用此擴展方法,只需對IList
List<Product> products = GetProducts(); products.Shuffle();
雖然System.Random很方便,但它並不總是能提供足夠的隨機性。如果需要更高質量的隨機性,System.Security.Cryptography庫提供了一個更安全的隨機數生成器:
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; } } }
在第一個示例中使用的System.Random類不是線程安全的。這意味著如果多個線程同時嘗試訪問同一個System.Random實例,則可能會出現不正確的結果。為了解決這個問題,ThreadSafeRandom類通過使用線程局部隨機數生成器提供了一種線程安全的解決方案。使用ThreadSafeRandom的修改後的Shuffle()擴展方法確保了在多線程環境中的正確性。
在隨機化泛型列表時,開發人員可以在使用System.Random(為了方便)或System.Security.Cryptography(為了更好的隨機性)的Fisher-Yates洗牌擴展方法之間進行選擇。此外,ThreadSafeRandom類有助於確保在多線程應用程序中的線程安全。具體方法取決於所需的隨機性和性能考慮。
以上是如何有效,安全地在C#中隨機地列出一個通用列表?的詳細內容。更多資訊請關注PHP中文網其他相關文章!