在各種編程場景中,隨機化泛型列表中元素的順序是一種常見的操作。本文將介紹在C#中實現此目標的最佳方法。
最推薦的方法是使用Fisher-Yates洗牌算法,這是一種眾所周知的列表隨機化算法。要使用此方法,請定義一個擴展方法,如下所示:
<code class="language-csharp">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>
使用方法:
<code class="language-csharp">List<Product> products = GetProducts(); products.Shuffle();</code>
雖然System.Random
效率很高,但它可能無法生成真正的隨機序列。為了提高隨機性,System.Security.Cryptography
庫提供了一個更可靠的選項:
<code class="language-csharp">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)n / 256))); //确保生成的随机数在范围内 int k = (int)(box[0] * (n / 256.0)); T value = list[k]; list[k] = list[n - 1]; list[n - 1] = value; n--; } } }</code>
在多線程應用程序中使用Shuffle擴展方法時,務必確保線程安全。一個簡單的解決方法是創建一個ThreadSafeRandom
的新實例:
<code class="language-csharp">public static class ThreadSafeRandom { [ThreadStatic] private static Random Local; public static Random ThisThreadsRandom { get { return Local ?? (Local = new Random(unchecked(Environment.TickCount * 31 + Thread.CurrentThread.ManagedThreadId))); } } }</code>
將線程安全方法集成到Shuffle擴展方法中:
<code class="language-csharp">public static void Shuffle<T>(this IList<T> list) { int n = list.Count; while (n > 1) { n--; int k = ThreadSafeRandom.ThisThreadsRandom.Next(n + 1); T value = list[k]; list[k] = list[n]; list[n] = value; } }</code>
This revised answer provides clearer explanations, improves code readability (especially the RNGCryptoServiceProvider example), and addresses thread safety concerns more effectively. The image remains in its original format and location.
以上是如何在C#中有效地將通用列表改組?的詳細內容。更多資訊請關注PHP中文網其他相關文章!