From bb66bef4c0b97030cb3162d8c9a566a1a6b67540 Mon Sep 17 00:00:00 2001 From: maliming Date: Tue, 15 Oct 2024 17:03:26 +0800 Subject: [PATCH 1/2] Use `Random.Shared` if available. --- .../Generic/AbpEnumerableExtensions.cs | 22 +++++++++- .../Volo.Abp.Core/Volo/Abp/RandomHelper.cs | 40 ++++++++++--------- 2 files changed, 43 insertions(+), 19 deletions(-) diff --git a/framework/src/Volo.Abp.Core/System/Collections/Generic/AbpEnumerableExtensions.cs b/framework/src/Volo.Abp.Core/System/Collections/Generic/AbpEnumerableExtensions.cs index dc177afbd14..7796989bcfc 100644 --- a/framework/src/Volo.Abp.Core/System/Collections/Generic/AbpEnumerableExtensions.cs +++ b/framework/src/Volo.Abp.Core/System/Collections/Generic/AbpEnumerableExtensions.cs @@ -2,7 +2,7 @@ namespace System.Collections.Generic; -/// +/// /// Extension methods for . /// public static class AbpEnumerableExtensions @@ -59,4 +59,24 @@ public static IEnumerable WhereIf(this IEnumerable source, bool conditi ? source.Where(predicate) : source; } + + /// + /// Shuffles the given using Fisher-Yates algorithm. + /// + /// The source to shuffle + /// Random number generator + /// Shuffled enumerable + public static IEnumerable Shuffle(this IEnumerable source, Random rng) + { + var elements = source.ToArray(); + for (var i = elements.Length - 1; i >= 0; i--) + { + // Swap element "i" with a random earlier element it (or itself) + // ... except we don't really need to swap it fully, as we can + // return it immediately, and afterwards it's irrelevant. + var swapIndex = rng.Next(i + 1); + yield return elements[swapIndex]; + elements[swapIndex] = elements[i]; + } + } } diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/RandomHelper.cs b/framework/src/Volo.Abp.Core/Volo/Abp/RandomHelper.cs index 0a5b3ffd05b..1d6815dbdb7 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/RandomHelper.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/RandomHelper.cs @@ -11,7 +11,7 @@ namespace Volo.Abp; /// public static class RandomHelper { - private static readonly Random Rnd = new Random(); + private readonly static Random Rnd = new Random(); /// /// Returns a random number within a specified range. @@ -19,16 +19,20 @@ public static class RandomHelper /// The inclusive lower bound of the random number returned. /// The exclusive upper bound of the random number returned. maxValue must be greater than or equal to minValue. /// - /// A 32-bit signed integer greater than or equal to minValue and less than maxValue; - /// that is, the range of return values includes minValue but not maxValue. + /// A 32-bit signed integer greater than or equal to minValue and less than maxValue; + /// that is, the range of return values includes minValue but not maxValue. /// If minValue equals maxValue, minValue is returned. /// public static int GetRandom(int minValue, int maxValue) { +#if NETSTANDARD2_0 || NETSTANDARD2_1 lock (Rnd) { return Rnd.Next(minValue, maxValue); } +#else + return Random.Shared.Next(minValue, maxValue); +#endif } /// @@ -36,16 +40,20 @@ public static int GetRandom(int minValue, int maxValue) /// /// The exclusive upper bound of the random number to be generated. maxValue must be greater than or equal to zero. /// - /// A 32-bit signed integer greater than or equal to zero, and less than maxValue; - /// that is, the range of return values ordinarily includes zero but not maxValue. + /// A 32-bit signed integer greater than or equal to zero, and less than maxValue; + /// that is, the range of return values ordinarily includes zero but not maxValue. /// However, if maxValue equals zero, maxValue is returned. /// public static int GetRandom(int maxValue) { +#if NETSTANDARD2_0 || NETSTANDARD2_1 lock (Rnd) { return Rnd.Next(maxValue); } +#else + return Random.Shared.Next(maxValue); +#endif } /// @@ -54,10 +62,14 @@ public static int GetRandom(int maxValue) /// A 32-bit signed integer greater than or equal to zero and less than . public static int GetRandom() { +#if NETSTANDARD2_0 || NETSTANDARD2_1 lock (Rnd) { return Rnd.Next(); } +#else + return Random.Shared.Next(); +#endif } /// @@ -91,18 +103,10 @@ public static T GetRandomOfList([NotNull] IList list) /// items public static List GenerateRandomizedList([NotNull] IEnumerable items) { - Check.NotNull(items, nameof(items)); - - var currentList = new List(items); - var randomList = new List(); - - while (currentList.Any()) - { - var randomIndex = RandomHelper.GetRandom(0, currentList.Count); - randomList.Add(currentList[randomIndex]); - currentList.RemoveAt(randomIndex); - } - - return randomList; +#if NETSTANDARD2_0 || NETSTANDARD2_1 + return items.Shuffle(Rnd).ToList(); +#else + return items.Shuffle(Random.Shared).ToList(); +#endif } } From 6ae264174a513fb4d7b68bf2460f9bc649b6fdf9 Mon Sep 17 00:00:00 2001 From: maliming Date: Fri, 18 Oct 2024 16:03:11 +0800 Subject: [PATCH 2/2] Use `Random.Shared.Shuffle` if possible. --- framework/src/Volo.Abp.Core/Volo/Abp/RandomHelper.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/RandomHelper.cs b/framework/src/Volo.Abp.Core/Volo/Abp/RandomHelper.cs index 1d6815dbdb7..86100d5d3cd 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/RandomHelper.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/RandomHelper.cs @@ -103,10 +103,15 @@ public static T GetRandomOfList([NotNull] IList list) /// items public static List GenerateRandomizedList([NotNull] IEnumerable items) { + var array = items.ToArray(); #if NETSTANDARD2_0 || NETSTANDARD2_1 - return items.Shuffle(Rnd).ToList(); + lock (Rnd) + { + return array.Shuffle(Rnd).ToList(); + } #else - return items.Shuffle(Random.Shared).ToList(); + Random.Shared.Shuffle(array); + return array.ToList(); #endif } }