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..86100d5d3cd 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,15 @@ 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 array = items.ToArray(); +#if NETSTANDARD2_0 || NETSTANDARD2_1 + lock (Rnd) { - var randomIndex = RandomHelper.GetRandom(0, currentList.Count); - randomList.Add(currentList[randomIndex]); - currentList.RemoveAt(randomIndex); + return array.Shuffle(Rnd).ToList(); } - - return randomList; +#else + Random.Shared.Shuffle(array); + return array.ToList(); +#endif } }