我可以在c#中使用LINQ可靠地生成随机数吗?

本文关键字:随机数 LINQ 我可以 | 更新日期: 2023-09-27 18:17:48

我熟悉RandomRNGCryptoServiceProvider,以及如何使用它们在c#中生成随机数。

但我也知道以下方法:

int start = 10;
int end = 50;
Enumerable.Range(start, end).OrderBy(o => Guid.NewGuid()).Take(5);

考虑到LINQ的流处理能力和此方法的线程安全性(与使用共享Random相反),我找不到不使用此方法的理由。

除了性能,我还错过了什么?

我可以在c#中使用LINQ可靠地生成随机数吗?

Guid类旨在创建唯一的数字,而不是随机的数字。

不能保证得到均匀分布。对于加密相关的任务,它肯定不安全。

只使用最适合某项任务的类。Random用于快速伪随机数据,RNGCryptoServiceProvider用于安全性。

Linq方法是一个hack。当您遇到线程问题时,请以既定的方式使其线程安全。

如果你想使用linq接口,我建议这样做:

public IEnumerable<int> GetRandomSequence(int start, int end)
{
    var generator = new Random();
    while (true)
        yield return generator.Next(start, end);
}

var randomSequence = GetRandomSequence(10, 50).Take(5);

但是在这种情况下,使用计数器而不是"while (true)"会更安全,以避免无限循环:

var sequence = GetRandomSequence();
var someOtherSequence = sequence.Skip(5); // here we forget to call Take, Zip, TakeWhile etc.
// some code
var someVar = someOtherSequence.ToList(); // endless call here
var someOtherVar = someOtherSequence.Join( ... ) // and here

您的技术的问题(或可能的好处?)是它不会重复范围内的任何数字。

在真正的随机集中,您可以合理地看到一个数字偶尔重复。

示例: {12, 46, 12, 27, 12}应该是有效的输出。

使用您的方法,您将永远不会看到12重复。
如果您希望以随机顺序返回数字10-50,但每个数字只返回一次,那么您真的需要一个洗牌算法