在 .NET 中生成随机数时,选择合适的类和方法对程序的安全性、性能和结果的随机性至关重要。使用不当可能导致可预测的结果或并发问题。以下是关键的最佳实践。
使用 Random 和 Thread-Safety
Random 类适用于大多数非加密场景,比如游戏逻辑或模拟。但要注意它不是线程安全的。
避免多个线程共享同一个 Random 实例,否则可能产生异常或重复值。推荐做法是:
每个线程使用独立的 Random 实例 通过 ThreadLocalprivate static readonly ThreadLocal<Random> _random = new ThreadLocal<Random>(() => new Random());
需要密码学安全时使用 RandomNumberGenerator
如果用于生成令牌、密钥或敏感数据,必须使用 System.Security.Cryptography.RandomNumberGenerator。
它提供加密强度的随机字节,适合安全相关用途。
常见用法:
生成随机字节数组 转换为整数或字符串(如唯一ID) 不要用于性能敏感的大量随机数生成 示例:byte[] data = new byte[4]; RandomNumberGenerator.Fill(data); int secureValue = BitConverter.ToInt32(data, 0);
避免频繁创建 Random 实例
短时间内创建多个 Random 实例(尤其是基于时间种子)会导致相同序列,因为默认种子来自系统时钟。
例如在循环中 new Random() 会得到重复值。
正确做法:
复用单个实例(注意线程问题) 使用 ThreadLocal 或工厂模式隔离实例考虑使用 System.Random 的新 API(.NET 6+)
.NET 6 引入了改进的方法,如 Random.Shared,提供线程安全的共享实例。
适用于轻量级、低竞争场景。
示例:int value = Random.Shared.Next(1, 100);
方便且安全,但在高并发下可能成为瓶颈,需根据负载评估。
基本上就这些。根据场景选对工具,注意线程和安全性,就能避免常见陷阱。