Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 64 additions & 1 deletion csharp/Platform.Random.Tests/RandomHelpersTests.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,76 @@
using Xunit;
using System.Threading.Tasks;
using System.Threading;

namespace Platform.Random.Tests
{
public class RandomHelpersTests
{
[Fact]
public void DefaultFieldTest()
public void DefaultPropertyTest()
{
Assert.NotNull(RandomHelpers.Default);
Assert.Same(RandomHelpers.Default, RandomHelpers.Default);
}

[Fact]
public void ThreadLocalPropertyTest()
{
Assert.NotNull(RandomHelpers.ThreadLocal);
Assert.Same(RandomHelpers.ThreadLocal, RandomHelpers.ThreadLocal);
}

[Fact]
public async Task ThreadLocalPropertyReturnsDifferentInstancesForDifferentThreadsTest()
{
System.Random mainThreadRandom = RandomHelpers.ThreadLocal;
System.Random? otherThreadRandom = null;

var task = Task.Run(() =>
{
otherThreadRandom = RandomHelpers.ThreadLocal;
});

await task;

Assert.NotNull(mainThreadRandom);
Assert.NotNull(otherThreadRandom);
Assert.NotSame(mainThreadRandom, otherThreadRandom);
}

[Fact]
public void CreateMethodTest()
{
var random1 = RandomHelpers.Create();
var random2 = RandomHelpers.Create();

Assert.NotNull(random1);
Assert.NotNull(random2);
Assert.NotSame(random1, random2);
}

[Fact]
public void CreateWithSeedMethodTest()
{
const int seed = 12345;
var random1 = RandomHelpers.Create(seed);
var random2 = RandomHelpers.Create(seed);

Assert.NotNull(random1);
Assert.NotNull(random2);
Assert.NotSame(random1, random2);

Assert.Equal(random1.Next(100), random2.Next(100));
}

[Fact]
public void CreateSecureMethodTest()
{
var secureRandom1 = RandomHelpers.CreateSecure();
var secureRandom2 = RandomHelpers.CreateSecure();

Assert.NotNull(secureRandom1);
Assert.NotNull(secureRandom2);
}
}
}
63 changes: 58 additions & 5 deletions csharp/Platform.Random/RandomHelpers.cs
Original file line number Diff line number Diff line change
@@ -1,15 +1,68 @@
using System.Threading;

namespace Platform.Random
{
/// <summary>
/// <para>Contains field-helper for <see cref="System.Random"/> class.</para>
/// <para>Содержит вспомогательное поле для класса <see cref="System.Random"/>.</para>
/// <para>Contains factory methods and properties for <see cref="System.Random"/> class.</para>
/// <para>Содержит фабричные методы и свойства для класса <see cref="System.Random"/>.</para>
/// </summary>
public static class RandomHelpers
{
private static readonly System.Lazy<System.Random> _default = new System.Lazy<System.Random>(() => new System.Random());

private static readonly ThreadLocal<System.Random> _threadLocal = new ThreadLocal<System.Random>(() => new System.Random());

/// <summary>
/// <para>Returns the pseudorandom number generator that is using the time of the first access to this field as seed.</para>
/// <para>Возвращает генератор псевдослучайных чисел использующий в качестве seed время первого обращения к этому полю.</para>
/// <para>Returns the pseudorandom number generator that is using the time of the first access to this property as seed.</para>
/// <para>Возвращает генератор псевдослучайных чисел использующий в качестве seed время первого обращения к этому свойству.</para>
/// </summary>
public static readonly System.Random Default = new System.Random(System.DateTime.UtcNow.Ticks.GetHashCode());
public static System.Random Default => _default.Value;

/// <summary>
/// <para>Returns a thread-local pseudorandom number generator that provides thread-safe access.</para>
/// <para>Возвращает локальный для потока генератор псевдослучайных чисел, обеспечивающий потокобезопасный доступ.</para>
/// </summary>
public static System.Random ThreadLocal => _threadLocal.Value!;

/// <summary>
/// <para>Creates a new pseudorandom number generator using system time as seed.</para>
/// <para>Создаёт новый генератор псевдослучайных чисел используя системное время в качестве seed.</para>
/// </summary>
/// <returns>
/// <para>A new instance of <see cref="System.Random"/>.</para>
/// <para>Новый экземпляр <see cref="System.Random"/>.</para>
/// </returns>
public static System.Random Create() => new System.Random();

/// <summary>
/// <para>Creates a new pseudorandom number generator using the specified seed value.</para>
/// <para>Создаёт новый генератор псевдослучайных чисел используя указанное значение seed.</para>
/// </summary>
/// <param name="seed">
/// <para>A number used to calculate a starting value for the pseudo-random number sequence.</para>
/// <para>Число, используемое для вычисления начального значения последовательности псевдослучайных чисел.</para>
/// </param>
/// <returns>
/// <para>A new instance of <see cref="System.Random"/>.</para>
/// <para>Новый экземпляр <see cref="System.Random"/>.</para>
/// </returns>
public static System.Random Create(int seed) => new System.Random(seed);

/// <summary>
/// <para>Creates a cryptographically secure pseudorandom number generator.</para>
/// <para>Создаёт криптографически стойкий генератор псевдослучайных чисел.</para>
/// </summary>
/// <returns>
/// <para>A new instance of cryptographically secure random number generator.</para>
/// <para>Новый экземпляр криптографически стойкого генератора случайных чисел.</para>
/// </returns>
public static System.Security.Cryptography.RandomNumberGenerator CreateSecure()
{
#if NET6_0_OR_GREATER
return System.Security.Cryptography.RandomNumberGenerator.Create();
#else
return new System.Security.Cryptography.RNGCryptoServiceProvider();
#endif
}
}
}
Loading