对泛型列表(例如数字列表)进行随机排序是编程中的一项常见任务。在C#中,有多种方法可以使用内置方法、扩展方法甚至第三方库来实现此目的。了解最佳方法和局限性对于获得最佳性能和正确性至关重要。
最常用的方法之一是使用Fisher-Yates洗牌算法。此方法通过重复交换具有随机索引的元素来随机打乱IList
<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
<code class="language-csharp">List<Product> products = GetProducts(); products.Shuffle();</code>
虽然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类有助于确保在多线程应用程序中的线程安全。具体方法取决于所需的随机性和性能考虑。
以上是我如何有效,安全地随机地将通用列表随机供应?的详细内容。更多信息请关注PHP中文网其他相关文章!