最常用方式是复用同一Random实例,避免循环中重复创建;多线程应使用Random.Shared(.NET 6+)或ThreadLocal;安全场景必须用RandomNumberGenerator。
Random 类生成基本随机数最常用也最直接的方式是实例化 Random 类,然后调用它的方法。注意:不要在循环里反复新建 Random 实例,否则可能因种子相同导致重复序列。
推荐做法是复用同一个实例,尤其在高频调用场景下:
var rand = new Random(); int num = rand.Next(); // 0 到 int.MaxValue 之间 int range = rand.Next(1, 101); // 1 到 100(不含 101) double d = rand.NextDouble(); // [0.0, 1.0)
Random 在多线程下不安全Random 实例不是线程安全的。多个线程同时调用 Next() 可能抛出 InvalidOperationException 或返回异常值(如负数、超限值)。
解决方案有三种,按推荐顺序:
ThreadLocal 每线程隔离实例Random.Shared(.NET 6+,静态、线程安全).NET 6 起推荐写法:
int safeNum = Random.Shared.Next(1, 101);
Random
Random 和 Random.Shared 都是伪随机,可预测,**绝不能用于生成 Token、加密密钥、验证码盐值等安全敏感场景**。
应改用 System.Security.Cryptography.RandomNumberGenerator:
var bytes = new byte[4]; RandomNumberGenerator.Fill(bytes); int cryptoRand = BitConverter.ToInt32(bytes) & 0x7FFFFFFF;
这个值不可预测,但开销比 Random 高一个数量级,只在真正需要时用。
容易被忽略的点:
Next(min, max) 的 max 是**排他上限**,比如 Next(0, 5) 只返回 0–4Random 算法不同,同一种子产生的序列不一致
Random 传固定种子(如 new Random(42))适合测试,但线上必须省略参数或用系统时间Update() 里每帧 new Random(),大概率得到一串相同数字种子逻辑本身不难,但错一次就可能让“随机”变成“固定”,尤其在分布式或高并发服务里,得盯紧实例生命周期和调用上下文。