.NET 8 Preview 1 中新增的 Random 方法

Intro

在 .NET 8 Preview 1 中引入了两个非常实用的 Random 方法,GetItems 和 Shuffle,下面我们简单的看个简单的示例吧

Sample

GetItems

GetItems 就是从一些选项中随机获取一些数据,有时候需要随机生成一些数据的时候会比较有用.

Sample 来了

private static readonly char[] ConstantNumbers = new[]
{
    '0',
    '1',
    '2',
    '3',
    '4',
    '5',
    '6',
    '7',
    '8',
    '9'
};

var randomCodeChars = Random.Shared.GetItems(ConstantNumbers, 6);
var randomCode = new string(randomCodeChars);
Console.WriteLine(randomCode);

输出结果如下:

.NET 8 Preview 1 中新增的 Random 方法

GetItems-01

我们不仅可以获取一个集合,也可以往一个已有的数组里进行填充

var charArray = new char[6]; 
Random.Shared.GetItems(ConstantNumbers, charArray.AsSpan());
Console.WriteLine(new string(charArray));

效果和前面的基本一样

实现代码如下:

public void GetItems<T>(ReadOnlySpan<T> choices, Span<T> destination)
{
    if (choices.IsEmpty)
        throw new ArgumentException(SR.Arg_EmptySpan, nameof(choices));

    for (int i = 0; i < destination.Length; i++)
    {
        destination[i] = choices[Next(choices.Length)];
    }
}

public T[] GetItems<T>(T[] choices, int length)
{
    ArgumentNullException.ThrowIfNull(choices);
    return GetItems(new ReadOnlySpan<T>(choices), length);
}

public T[] GetItems<T>(ReadOnlySpan<T> choices, int length)
{
    if (length < 0)
        throw new ArgumentOutOfRangeException(nameof(length), SR.ArgumentOutOfRange_NeedNonNegNum);

    T[] items = new T[length];
    GetItems<T>(choices, items.AsSpan());
    return items;
}

Shuffle

Shuffle  方法是将已有集合重新洗牌,重新随机排序,来看一个简单的示例:

var nums = Enumerable.Range(1, 10).ToArray();
Random.Shared.Shuffle(nums);
Console.WriteLine($"Numbers shuffled:\n {JsonSerializer.Serialize(nums)}");

输出结果类似下面这样:

.NET 8 Preview 1 中新增的 Random 方法

shuffle

实现代码如下:

public void Shuffle<T>(T[] values)
{
    ArgumentNullException.ThrowIfNull(values);
    Shuffle<T>(values.AsSpan());
}

public void Shuffle<T>(Span<T> values)
{
    int n = values.Length;

    for (int i = 0; i < n - 1; i++)
    {
        int j = Next(i, n);

        if (j != i)
        {
            T temp = values[i];
            values[i] = values[j];
            values[j] = temp;
        }
    }
}

More

这两个方法感觉还是非常的实用的,除了 Random 类外还有一个 RandomNumberGenerator 中也引入了这两个方法,以及基于此的两个方法

string GetString(ReadOnlySpan<char> choices, int length)

string GetHexString(int stringLength, bool lowercase = false)

void GetHexString(Span<char> destination, bool lowercase = false)

public static void GetString()
{
    var randomCode = RandomNumberGenerator.GetString(ConstantNumbers, 6);
    Console.WriteLine(randomCode);
}

public static void GetHexString()
{
    var randomHexString = RandomNumberGenerator.GetHexString(6);
    Console.WriteLine(randomHexString);

    var charArray = new char[6];
    RandomNumberGenerator.GetHexString(charArray, true);
    Console.WriteLine(new string(charArray));
}

.NET 8 Preview 1 中新增的 Random 方法

RandomNumberGenerator

详细可以参考 PR:

https://github.com/dotnet/runtime/pull/78598/files#diff-37a7bb8eb00892263f0be9d5ab9db2f925a9bb5651bc310e66e646d05dd2847c