Random()不加参数时默认用系统时钟毫秒数作种子,若短时间内频繁新建实例会导致种子相同、生成相同数字;正确做法是全局或静态复用单个Random实例。

Random() 构造函数不加参数,为什么每次跑都出一样数字?
因为 Random 默认用系统时钟毫秒数做种子,如果在极短时间内(比如循环里)反复新建实例,会拿到相同种子,结果就全一样。
- ✅ 正确做法:全局或静态声明一个
Random实例,复用它 - ❌ 错误写法:
for (int i = 0; i - ⚠️ 多线程下更危险:
Random不是线程安全的,高并发时可能抛ArgumentOutOfRangeException
Next()、Next(int)、Next(int, int) 三个重载怎么选?
它们决定随机数范围和是否包含边界,容易混淆的是闭开区间规则 —— Next(min, max) 返回的是 [min, max),即含最小值、不含最大值。
-
Next():返回非负整数,上限是int.MaxValue(约 21 亿),基本不用 -
Next(int maxValue):等价于Next(0, maxValue),生成[0, maxValue) -
Next(int minValue, int maxValue):唯一能指定下界的,注意maxValue必须大于minValue,否则抛ArgumentException
比如要生成 1–6 的骰子点数,得写 r.Next(1, 7),不是 Next(1, 6)。
想生成真随机数(比如密码、加密盐),还能用 Random 吗?
不能。Random 是伪随机,可预测、不可用于安全场景。.NET 提供了 RandomNumberGenerator(位于 System.Security.Cryptography)来替代。
-
Random适合游戏、测试数据、UI 动画等对安全性无要求的场景 - 需要密码学安全时,用
RandomNumberGenerator.GetInt32(int, int)(.NET 6+)或手动读取字节数组再转换 - 旧版本(.NET Core 2.1 / .NET Framework)需用
RandomNumberGenerator.Create().GetBytes(...)+ 自己映射到整数范围
为什么有时 Next() 返回负数?
不会。只要没传错参数,Next() 和 Next(int) 永远返回非负数;只有 Next(int, int) 可能返回负数 —— 当你把 minValue 设成负数时,比如 r.Next(-10, -1) 会返回 -10 到 -2 之间的整数。
- 常见误判:看到负数以为是 bug,其实是自己写了负的下界
- 另一个可能:变量类型是
int,但你用uint接收又没检查溢出,导致显示异常 - 调试建议:直接打印
typeof(T).Name和原始值,别依赖 IDE tooltip
伪随机的核心约束就两条:别频繁 new,别拿它当密码学工具。其余都是围绕这两条展开的细节。










