C#生成不重复随机字符串工具类封装

Evan
Evan
发布时间:2026-10-14| 1人浏览过
原创

本文分享 C# 中构建不重复随机字符串的工具类方案,涵盖纯数字、混合字符及自定义源列表三种场景,并指出基础 Random 类的线程安全性问题。

结果或目标:生成唯一序列

在实际开发中(如短信验证码、临时 ID),需要一种能快速生成“看似无序且无重复”字符串的机制。对于短周期内的少量请求,传统伪随机数生成器已足够;若涉及高并发或极长生命周期,需采用 Guid.NewGuid().ToString() 保证绝对唯一。

准备条件

  1. 环境要求:.NET Framework 4.0+ 或 .NET Core / .NET 5+。
  2. 核心类库:System.Diagnostics 用于获取毫秒级时间戳作为随机种子,防止连续调用时出现重复序列。
  3. 依赖项:无需额外 NuGet 包。

真实操作顺序:实现随机策略

第1步:初始化安全随机种子

目的:解决多线程环境下 Random 类因同一毫秒内生成相同种子导致返回固定值的问题。

  • 输入参数:无直接入参,依赖内部计数器与系统时钟。
  • 动作:使用 DateTime.Now.Ticks 累加偏移量,构造 int 型种子。
  • 完成状态:每次实例化随机对象时种子均不相同。
private int rep = 0;
public void SafeInitRandom()
{
    long num2 = DateTime.Now.Ticks + this.rep;
    this.rep++;
    // 确保生成的种子覆盖高位和低位,减少重复概率
    int seed = ((int)(((ulong)num2) & 0xffffffffL)) | ((int)(num2 >> 3));
    return new Random(seed);
}

第2步:纯数字字符串生成

目的:适用于仅包含 '0'-'9' 的校验码(如 4-6 位数字验证码)。

  • 入口:配置 GenerateCheckCodeNum(int codeCount)。
  • 参数:codeCount 指定目标长度。
  • 逻辑:random.Next() % 10 取余后映射到 ASCII 字符 '0' (0x30)。
public string GenerateCheckCodeNum(int codeCount)
{
    string str = string.Empty;
    Random random = GetSafeRandom();
    for (int i = 0; i < codeCount; i++)
    {
        int num = random.Next();
        str += Convert.ToChar(0x30 + (num % 10)).ToString();
    }
    return str;
}

第3步:混合字符(数字+大写字母)生成

目的:增加字符复杂度,常用于图形验证码。

  • 动作:根据 random.Next() % 2 决定取值范围。
  • 关键参数:偶数取 0x30-0x39 (数字),奇数取 0x41-0x5A (A-Z)。
public string GenerateMixedCode(int codeCount)
{
    string str = string.Empty;
    Random random = GetSafeRandom();
    for (int i = 0; i < codeCount; i++)
    {
        int num = random.Next();
        char ch;
        if ((num % 2) == 0)
        {
            ch = Convert.ToChar(0x30 + (num % 10)); // 数字
        }
        else
        {
            ch = Convert.ToChar(0x41 + (num % 26)); // A-Z
        }
        str += ch.ToString();
    }
    return str;
}

第4步:自定义源列表去重抽取

目的:从用户指定的字符池(如排除易混淆字符 l/1, o/0)中随机选取且不重复。

  • 风险提醒:此方法依赖于随机数的局部连续性,在高频率调用下可能产生相似结尾,生产环境建议使用 Fisher-Yates Shuffle 算法打乱数组后截取前 N 个元素。
  • 动作:将源字符串按逗号分割为数组,循环抽取索引。
private string GetRandomFromSource(string sourceString, int count)
{
    string[] chars = sourceString.Split(',');
    string result = "";
    int lastIdx = -1;
    Random rand = GetSafeRandom();

    for (int i = 0; i < count; i++)
    {
        int idx;
        // 简单的防相邻重复逻辑
        do 
        {
            idx = rand.Next(chars.Length);
        } while (idx == lastIdx);
        
        lastIdx = idx;
        result += chars[idx];
    }
    return result;
}

完成判断与排错

完成标准:
1. 单次调用 GenerateMixedCode(6) 返回 6 位由数字和大写字母组成的字符串。
2. 短时间内连续调用多次(如 1000 次),未发生完全相同的两个序列返回。

常见问题:
- 问题描述:多个线程同时调用时,有时会产生相同的随机串。
- 解决方案:这是 System.Random 非线程安全的特性。在生产环境中应使用 ThreadLocal<Random> 或改用 RNGCryptoServiceProvider(虽然速度稍慢,但加密级安全)。

简要总结

C# 中生成随机字符串的核心在于控制种子算法以规避重复。上述工具类涵盖了最常见的三种业务需求场景,可直接集成至项目中。

以下是一个类似的 Go 语言实现思路,展示了不同语言处理此类问题的差异:

package main
import (
	"fmt"
	"math/rand"
	"time"
)
func generateRandCode(length int) string {
	chars := []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
	result := make([]byte, length)
	rand.Seed(time.Now().UnixNano())
	for i := 0; i < length; i++ {
		result[i] = chars[rand.Intn(len(chars))]
	}
	return string(result)
}

以上就是C#生成不重复随机字符串工具的详细内容,更多关于C#随机数编程的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。