RandomExtensions
Provides random data generation.
using System;
using System.Security.Cryptography;
namespace DotNext
{
public static class RandomExtensions
{
private interface IRandomCharacterGenerator
{
char NextChar(ReadOnlySpan<char> allowedChars);
}
private readonly struct RandomCharacterGenerator : IRandomCharacterGenerator
{
private readonly Random random;
internal RandomCharacterGenerator(Random random)
{
this.random = random;
}
char IRandomCharacterGenerator.NextChar(ReadOnlySpan<char> allowedChars)
{
return allowedChars[random.Next(0, allowedChars.Length)];
}
}
private readonly struct RNGCharacterGenerator : IRandomCharacterGenerator
{
private readonly byte[] buffer;
private readonly RandomNumberGenerator random;
internal RNGCharacterGenerator(RandomNumberGenerator random)
{
this.random = random;
buffer = new byte[4];
}
char IRandomCharacterGenerator.NextChar(ReadOnlySpan<char> allowedChars)
{
random.GetBytes(buffer, 0, 4);
int index = (BitConverter.ToInt32(buffer, 0) & 2147483647) % allowedChars.Length;
return allowedChars[index];
}
}
internal static readonly int BitwiseHashSalt = new Random().Next();
private unsafe static string NextString<R>(ref R generator, ReadOnlySpan<char> allowedChars, int length) where R : struct, IRandomCharacterGenerator
{
if (length < 0)
throw new ArgumentOutOfRangeException("length");
if (length != 0) {
Span<char> span = (length < 1024) ? new Span<char>((void*)stackalloc byte[(int)checked(unchecked((ulong)(uint)length) * 2)], length) : new Span<char>(new char[length]);
Span<char> span2 = span;
for (int i = 0; i < span2.Length; i++) {
span2[i] = generator.NextChar(allowedChars);
}
fixed (char* value = &span.GetPinnableReference()) {
return new string(value, 0, length);
}
}
return "";
}
public static string NextString(this Random random, ReadOnlySpan<char> allowedChars, int length)
{
RandomCharacterGenerator generator = new RandomCharacterGenerator(random);
return NextString(ref generator, allowedChars, length);
}
public static string NextString(this Random random, char[] allowedChars, int length)
{
return random.NextString(new ReadOnlySpan<char>(allowedChars), length);
}
public static string NextString(this Random random, string allowedChars, int length)
{
return random.NextString(allowedChars.AsSpan(), length);
}
public static string NextString(this RandomNumberGenerator random, ReadOnlySpan<char> allowedChars, int length)
{
RNGCharacterGenerator generator = new RNGCharacterGenerator(random);
return NextString(ref generator, allowedChars, length);
}
public static string NextString(this RandomNumberGenerator random, char[] allowedChars, int length)
{
return random.NextString(new ReadOnlySpan<char>(allowedChars), length);
}
public static string NextString(this RandomNumberGenerator random, string allowedChars, int length)
{
return random.NextString(allowedChars.AsSpan(), length);
}
public static bool NextBoolean(this Random random, double trueProbability = 0.5)
{
if (!trueProbability.Between(0, 1, BoundType.Closed))
throw new ArgumentOutOfRangeException("trueProbability");
return random.NextDouble() >= 1 - trueProbability;
}
public static int Next(this RandomNumberGenerator random)
{
byte[] array = new byte[4];
random.GetBytes(array, 0, 4);
return BitConverter.ToInt32(array, 0) & 2147483647;
}
public static bool NextBoolean(this RandomNumberGenerator random, double trueProbability = 0.5)
{
if (!trueProbability.Between(0, 1, BoundType.Closed))
throw new ArgumentOutOfRangeException("trueProbability");
return random.NextDouble() >= 1 - trueProbability;
}
public static double NextDouble(this RandomNumberGenerator random)
{
double num = (double)random.Next();
return num / (num + 1);
}
}
}