diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetRandomCommand.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetRandomCommand.cs
index a8ad9deb22..c77c25c5f4 100644
--- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetRandomCommand.cs
+++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/GetRandomCommand.cs
@@ -1,199 +1,18 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System;
-using System.Collections.Generic;
-using System.Diagnostics.CodeAnalysis;
-using System.Globalization;
using System.Management.Automation;
-using System.Management.Automation.Runspaces;
-using System.Numerics;
-using System.Security.Cryptography;
-using System.Threading;
-
-using Debug = System.Management.Automation.Diagnostics;
namespace Microsoft.PowerShell.Commands
{
///
- /// This class implements get-random cmdlet.
+ /// This class implements `Get-Random` cmdlet.
///
- ///
- [Cmdlet(VerbsCommon.Get, "Random", DefaultParameterSetName = GetRandomCommand.RandomNumberParameterSet,
+ [Cmdlet(VerbsCommon.Get, "Random", DefaultParameterSetName = GetRandomCommandBase.RandomNumberParameterSet,
HelpUri = "https://go.microsoft.com/fwlink/?LinkID=2097016", RemotingCapability = RemotingCapability.None)]
[OutputType(typeof(int), typeof(long), typeof(double))]
- public class GetRandomCommand : PSCmdlet
+ public sealed class GetRandomCommand : GetRandomCommandBase
{
- #region Parameter set handling
-
- private const string RandomNumberParameterSet = "RandomNumberParameterSet";
- private const string RandomListItemParameterSet = "RandomListItemParameterSet";
- private const string ShuffleParameterSet = "ShuffleParameterSet";
-
- private static readonly object[] _nullInArray = new object[] { null };
-
- private enum MyParameterSet
- {
- Unknown,
- RandomNumber,
- RandomListItem
- }
-
- private MyParameterSet _effectiveParameterSet;
-
- private MyParameterSet EffectiveParameterSet
- {
- get
- {
- // cache MyParameterSet enum instead of doing string comparison every time
- if (_effectiveParameterSet == MyParameterSet.Unknown)
- {
- if ((MyInvocation.ExpectingInput) && (Maximum == null) && (Minimum == null))
- {
- _effectiveParameterSet = MyParameterSet.RandomListItem;
- }
- else if (ParameterSetName == GetRandomCommand.RandomListItemParameterSet
- || ParameterSetName == GetRandomCommand.ShuffleParameterSet)
- {
- _effectiveParameterSet = MyParameterSet.RandomListItem;
- }
- else if (ParameterSetName.Equals(GetRandomCommand.RandomNumberParameterSet, StringComparison.OrdinalIgnoreCase))
- {
- if ((Maximum != null) && (Maximum.GetType().IsArray))
- {
- InputObject = (object[])Maximum;
- _effectiveParameterSet = MyParameterSet.RandomListItem;
- }
- else
- {
- _effectiveParameterSet = MyParameterSet.RandomNumber;
- }
- }
- else
- {
- Debug.Assert(false, "Unrecognized parameter set");
- }
- }
-
- return _effectiveParameterSet;
- }
- }
-
- #endregion Parameter set handling
-
- #region Error handling
-
- private void ThrowMinGreaterThanOrEqualMax(object minValue, object maxValue)
- {
- if (minValue == null)
- {
- throw PSTraceSource.NewArgumentNullException("min");
- }
-
- if (maxValue == null)
- {
- throw PSTraceSource.NewArgumentNullException("max");
- }
-
- ErrorRecord errorRecord = new(
- new ArgumentException(string.Format(
- CultureInfo.InvariantCulture, GetRandomCommandStrings.MinGreaterThanOrEqualMax, minValue, maxValue)),
- "MinGreaterThanOrEqualMax",
- ErrorCategory.InvalidArgument,
- null);
-
- ThrowTerminatingError(errorRecord);
- }
-
- #endregion
-
- #region Random generator state
-
- private static readonly ReaderWriterLockSlim s_runspaceGeneratorMapLock = new();
-
- // 1-to-1 mapping of runspaces and random number generators
- private static readonly Dictionary s_runspaceGeneratorMap = new();
-
- private static void CurrentRunspace_StateChanged(object sender, RunspaceStateEventArgs e)
- {
- switch (e.RunspaceStateInfo.State)
- {
- case RunspaceState.Broken:
- case RunspaceState.Closed:
- try
- {
- GetRandomCommand.s_runspaceGeneratorMapLock.EnterWriteLock();
- GetRandomCommand.s_runspaceGeneratorMap.Remove(((Runspace)sender).InstanceId);
- }
- finally
- {
- GetRandomCommand.s_runspaceGeneratorMapLock.ExitWriteLock();
- }
-
- break;
- }
- }
-
- private PolymorphicRandomNumberGenerator _generator;
-
- ///
- /// Gets and sets generator associated with the current runspace.
- ///
- private PolymorphicRandomNumberGenerator Generator
- {
- get
- {
- if (_generator == null)
- {
- Guid runspaceId = Context.CurrentRunspace.InstanceId;
-
- bool needToInitialize = false;
- try
- {
- GetRandomCommand.s_runspaceGeneratorMapLock.EnterReadLock();
- needToInitialize = !GetRandomCommand.s_runspaceGeneratorMap.TryGetValue(runspaceId, out _generator);
- }
- finally
- {
- GetRandomCommand.s_runspaceGeneratorMapLock.ExitReadLock();
- }
-
- if (needToInitialize)
- {
- Generator = new PolymorphicRandomNumberGenerator();
- }
- }
-
- return _generator;
- }
-
- set
- {
- _generator = value;
- Runspace myRunspace = Context.CurrentRunspace;
-
- try
- {
- GetRandomCommand.s_runspaceGeneratorMapLock.EnterWriteLock();
- if (!GetRandomCommand.s_runspaceGeneratorMap.ContainsKey(myRunspace.InstanceId))
- {
- // make sure we won't leave the generator around after runspace exits
- myRunspace.StateChanged += CurrentRunspace_StateChanged;
- }
-
- GetRandomCommand.s_runspaceGeneratorMap[myRunspace.InstanceId] = _generator;
- }
- finally
- {
- GetRandomCommand.s_runspaceGeneratorMapLock.ExitWriteLock();
- }
- }
- }
-
- #endregion
-
- #region Common parameters
-
///
/// Seed used to reinitialize random numbers generator.
///
@@ -201,194 +20,6 @@ namespace Microsoft.PowerShell.Commands
[ValidateNotNull]
public int? SetSeed { get; set; }
- #endregion Common parameters
-
- #region Parameters for RandomNumberParameterSet
-
- ///
- /// Maximum number to generate.
- ///
- [Parameter(ParameterSetName = RandomNumberParameterSet, Position = 0)]
- public object Maximum { get; set; }
-
- ///
- /// Minimum number to generate.
- ///
- [Parameter(ParameterSetName = RandomNumberParameterSet)]
- public object Minimum { get; set; }
-
- private static bool IsInt(object o)
- {
- if (o == null || o is int)
- {
- return true;
- }
-
- return false;
- }
-
- private static bool IsInt64(object o)
- {
- if (o == null || o is long)
- {
- return true;
- }
-
- return false;
- }
-
- private static object ProcessOperand(object o)
- {
- if (o == null)
- {
- return null;
- }
-
- PSObject pso = PSObject.AsPSObject(o);
- object baseObject = pso.BaseObject;
-
- if (baseObject is string)
- {
- // The type argument passed in does not decide the number type we want to convert to. ScanNumber will return
- // int/long/double based on the string form number passed in.
- baseObject = System.Management.Automation.Language.Parser.ScanNumber((string)baseObject, typeof(int));
- }
-
- return baseObject;
- }
-
- private static double ConvertToDouble(object o, double defaultIfNull)
- {
- if (o == null)
- {
- return defaultIfNull;
- }
-
- double result = (double)LanguagePrimitives.ConvertTo(o, typeof(double), CultureInfo.InvariantCulture);
- return result;
- }
-
- #endregion
-
- #region Parameters and variables for RandomListItemParameterSet
-
- private List