醋醋百科网

Good Luck To You!

dotnet 10 Random GetString 支持

dotnet 10 Random GetString 支持

Intro

.NET 8 里引入了 Random.GetItemsRandomNumberGenerator.GetString/RandomNumberGenerator.GetHexString.NET 8 Preview 1 中新增的 Random 方法

在 .NET 10 Preview 3 中为 Random 也引入了

GetString/GetHexString 的支持,基于 Random 的使用更为方便对于简单的使用场景也比使用 RandomNumberGenerator 的性能更好一些

New API

新引入的 API 定义如下,和 RandomNumberGenerator 方法是类似的,只是 RandomNumberGenerator 的方法是 static 的,新增的方法是 Random 中的实例方法 :

namespace System;

public partial class Random
{
// same signatures as on RandomNumberGenerator, but instance instead of static
public string GetString(ReadOnlySpan<char> choices, int length);
public string GetHexString(int stringLength, bool lowercase = false);
public void GetHexString(Span<char> destination, bool lowercase = false);
}

提出 API 的一些描述如下,可以参考 api 提议的 issue:https://github.com/dotnet/runtime/issues/111956

我们为 RandomNumberGenerator 添加了 GetString 和 GetHexString 方法。Random 没有这些方法,但它们在这里同样有用。这些方法与加密安全性并没有太多特定的关系。开发人员需要通过使用 string.Create 然后调用 Random.GetItems 来填充后备空间。如果简单的重载对于 RandomNumberGenerator 是合理的,那么它们对 Random 同样适用。

Sample

使用方式和 RandomNumberGenerator 基本一致

Console.WriteLine("GetString");
var nums = "1234567890";
var randomString = Random.Shared.GetString(nums, 8);
Console.WriteLine(randomString);

Console.WriteLine("GetHexString");
var randomHexString = Random.Shared.GetHexString(16);
Console.WriteLine(randomHexString);
Console.WriteLine(Random.Shared.GetHexString(16, true));

Console.WriteLine("GetHexString Span");
Span<char> chars = stackallocchar[16];
Random.Shared.GetHexString(chars);
Console.WriteLine(chars);
Random.Shared.GetHexString(chars, true);
Console.WriteLine(chars);

如果要在之前的版本里使用,可以使用 RandomNumberGenerator 的 API 来代替

Console.WriteLine("RandomNumberGenerator");
var randString = RandomNumberGenerator.GetString(nums, 8);
Console.WriteLine(randString);
Console.WriteLine(RandomNumberGenerator.GetHexString(16));
Console.WriteLine(RandomNumberGenerator.GetHexString(16, true));
RandomNumberGenerator.GetHexString(chars);
Console.WriteLine(chars);
RandomNumberGenerator.GetHexString(chars, true);
Console.WriteLine(chars);

输出结果如下:

Benchmark

前面我们提到了性能更好,是否真的如此呢,我们可以做一个简单的 benchmark 来测试一下,benchmark 代码如下:

[ShortRunJob]
publicclassBenchmark
{
privatestaticreadonlychar[] Chars = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];

[Benchmark(Baseline = true)]
public string RandomGetString()
{
return Random.Shared.GetString(Chars, 8);
}


[Benchmark]
public string RandomNumberGeneratorGetString()
{
return RandomNumberGenerator.GetString(Chars, 8);
}
}

benchmark 结果如下:



benchmark result

从基准测试结果可以看出,Random 的性能更好,RandomNumberGeneratorGetString 方法耗时是 Random1.83

More

为什么 RandomNumberGeneratorRandom 慢?

  1. 1. 加密强度更高
    RandomNumberGenerator(例如 RandomNumberGenerator.GetBytes)基于加密算法(比如 AES 或操作系统提供的 CSPRNG)。这些算法设计目的是不可预测不可逆统计上随机,所以它们会消耗更多的 CPU 资源
  2. 2. 依赖系统熵源
    它通常从系统级熵源读取数据(比如 Linux 的 /dev/urandom 或 Windows 的 BCryptGenRandom),这会带来额外的 I/O 和同步开销
  3. 3. 线程安全和隔离机制
    加密用的 RNG 设计时考虑了线程安全、隔离和防止侧信道攻击,因此增加了锁、上下文校验和其他安全逻辑。
  4. 4. 不做缓存或简化
    Random 不同,RandomNumberGenerator 每次都从头生成随机数,不复用种子,不做简化,以保证安全性。

什么时候应该使用 RandomNumberGenerator

当你需要不可预测的随机数时,就应该使用它。比如:

  • o 生成密码、API 密钥、Token
  • o 为密码哈希生成盐值
  • o 生成加密密钥或 IV
  • o 生成安全的 Session ID
  • o 生成 nonce(一次性随机数)
  • o 任何预测 = 漏洞 的情况

总结:如果你的应用场景中,黑客能猜出“随机数”就会出问题,那就用 RandomNumberGenerator


什么时候用 Random 更合适?

当你不关心安全,只想要速度快、用法简单时,用 Random 或 .NET 6+ 的 Random.Shared

  • o 游戏机制(比如掷骰子、掉落奖励)
  • o 生成随机颜色或 UI 效果
  • o 模拟、测试或生成假数据
  • o 打乱顺序(非安全用途)
  • o 普通的概率判断逻辑

References

  • o https://github.com/dotnet/runtime/issues/111956
  • o https://github.com/dotnet/runtime/pull/112162
  • o https://github.com/WeihanLi/SamplesInPractice/blob/main/net10sample/Net10Samples/RandomSample.cs
  • o .NET 8 Preview 1 中新增的 Random 方法

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言