C#怎么生成随机数_C#如何获取指定范围内的不重复随机数【技巧】

穿越時空

穿越時空

2026-04-17

833人浏览

原创

应复用 random 实例或使用 random.shared;取不重复随机数优先洗牌(fisher-yates 更优),避免边生成边查重;动态场景用 hashset 高效去重。

c#怎么生成随机数_c#如何获取指定范围内的不重复随机数【技巧】

Random 生成基本随机数,但别在循环里反复 new

直接调用 new Random().Next() 看似简单,实际在高频调用(比如 for 循环内)会导致大量重复值——因为 Random 默认用系统时钟做种子,短时间多次实例化会拿到相同种子,从而产出相同序列。

正确做法是复用一个 Random 实例:

private static readonly Random _random = new Random();

如果需要线程安全(比如多线程并发取随机数),改用 Random.Shared(.NET 6+):

int value = Random.Shared.Next(1, 101); // [1, 101)
  • Next():返回非负整数(0 到 int.MaxValue
  • Next(int max):[0, max)
  • Next(int min, int max):[min, max),注意 max 不包含

要不重复的随机数?别边生成边查重,用洗牌更稳

“生成一个、检查是否已存在、重复就重试”这种逻辑在范围小、数量大时极易卡死(比如从 1–10 中取 9 个不重复数,最后几个可能反复碰撞)。更可靠的方式是先构造全集,再打乱顺序,然后截取。

例如取 5 个 1–20 之间不重复的随机整数:

var numbers = Enumerable.Range(1, 20).OrderBy(_ => Random.Shared.Next()).Take(5).ToArray();

这个写法简洁,但要注意:OrderBy 基于随机值排序,虽够用,但不是严格均匀洗牌(Fisher-Yates 更优)。如对统计分布敏感,应手写洗牌:

C函数速查手册(CHM版)
C函数速查手册(CHM版)

C函数速查手册(CHM版)

下载
var list = Enumerable.Range(1, 20).ToList();
for (int i = list.Count - 1; i > 0; i--)
{
    int j = Random.Shared.Next(i + 1);
    (list[i], list[j]) = (list[j], list[i]);
}
var result = list.Take(5).ToArray();

HashSet<int></int> 适合「动态决定取多少」的场景

当你要持续生成、直到满足某个条件(比如“生成直到和大于 100 的不重复随机数”),或无法预知要多少个时,HashSet 比预分配数组更自然:

var seen = new HashSet<int>();
while (seen.Count <ul>
<li>插入去重是 O(1) 平均复杂度,比 List.Contains 快得多</li>
<li>不保证顺序,如需升序/降序得额外调用 <code>OrderBy</code>
</li>
<li>注意:<code>HashSet.Add()</code> 返回 <code>bool</code>,可用来判断是否新增成功</li>
</ul>
<h3>小心 <code>Random</code> 在 Unity 或 ASP.NET Core 中的陷阱</h3>
<p>Unity 早期版本中 <code>Random</code> 是静态类(<code>UnityEngine.Random</code>),和 <code>System.Random</code> 完全无关,API 也不同(比如用 <code>Range(min, max)</code>)。混用会导致编译通过但行为异常。</p>
<p>ASP.NET Core 中若把 <code>Random</code> 实例注册为 Singleton 服务,要注意它不是线程安全的(<code>Random.Shared</code> 才是)。.NET 5 及以前必须加锁或换用 <code>ThreadLocal<random></random></code>。</p>
<p>最省心的底线方案:只要不是性能关键路径,一律用 <code>Random.Shared</code>(.NET 6+)或封装一层带锁的静态实例(旧框架)。</p>
<p>真正容易被忽略的是边界语义——<code>Next(1, 10)</code> 产生的是 1 到 9,不是 1 到 10;而 <code>NextDouble()</code> 返回 [0.0, 1.0),这些半开区间在做映射时稍不注意就会偏一格。</p></int>

相关专题

更多
c#是什么意思
c#是什么意思

C#是一种通用的面向对象编程语言,它在.NET框架上运行,可用于开发各种类型的应用程序。本专题为大家提供c#相关的各种文章、以及下载和课程。

2023.08.08

528

5

什么是c#
什么是c#

C#(读作C Sharp)是一种现代的、通用的、面向对象的编程语言。它由微软公司开发,于2000年首次发布,主要用于开发Windows桌面应用程序、Web应用程序、移动应用程序以及游戏开发等领域。C#是一种类型安全和托管的编程语言,它结合了C++的强大性能和C语言的简单易学特点,并引入了许多新的特性和概念,如委托、属性、泛型和异步编程等,以提高开发效率和代码可维护性。

2023.08.31

1181

3

C#中base关键字的用法
C#中base关键字的用法

在C#中,base关键字用于访问当前类的基类成员,这包括基类的字段、属性、方法、构造函数、索引器以及事件。想了解更多C#的相关内容,可以阅读本专题下面的文章。

2024.03.13

556

8

C#Task用法
C#Task用法

Task在C#中是用于表示异步操作的对象,它位于System.Threading.Tasks命名空间中。想了解更多C#中各种用法的相关内容,可以阅读本专题下面的文章。

2024.03.14

1051

11

C# 并发与异步编程
C# 并发与异步编程

本专题系统讲解 C# 异步编程与并发控制,重点介绍 async 和 await 关键字、Task 类、线程池管理、并发数据结构、死锁与线程安全问题。通过多个实战项目,帮助学习者掌握 如何在 C# 中编写高效的异步代码,提升应用的并发性能与响应速度。

2026.02.03

149

18

C# 多线程与异步编程
C# 多线程与异步编程

本专题深入讲解 C# 中多线程与异步编程的核心概念与实战技巧,包括线程池管理、Task 类的使用、async/await 异步编程模式、并发控制与线程同步、死锁与竞态条件的解决方案。通过实际项目,帮助开发者掌握 如何在 C# 中构建高并发、低延迟的异步系统,提升应用性能和响应速度。

2026.02.06

203

20

C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

2026.03.11

526

24

C# Unity游戏开发与ECS架构实践
C# Unity游戏开发与ECS架构实践

本专题聚焦 C# 在 Unity 游戏开发中的应用,系统讲解 ECS(Entity-Component-System)架构设计、游戏对象管理、性能优化与内存控制策略。通过实际游戏案例,帮助开发者构建高性能、结构清晰的游戏系统,提高游戏开发效率与运行性能。

2026.04.13

138

20

php中foreach用法
php中foreach用法

本专题整合了php中foreach用法的相关介绍,阅读专题下面的文章了解更多详细教程。

2025.12.04

450

13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
RabbitMQ 教程手册
RabbitMQ 教程手册

共0课时 | 0人学习

Linux man-pages 项目
Linux man-pages 项目

共0课时 | 0人学习

C# 教程
C# 教程

共94课时 | 20.2万人学习