Consider this function:
function Test-Discrimination
{
[CmdletBinding()]
param
(
[parameter(ValueFromPipeline = $true,
Mandatory = $true,
ParameterSetName = 'string')]
[string]
$String,
[parameter(ValueFromPipeline = $true,
Mandatory = $true,
ParameterSetName = 'hashtable')]
[hashtable]
$Hashtable,
[parameter(ValueFromPipeline = $true,
Mandatory = $true,
ParameterSetName = 'pscustomobject')]
[pscustomobject]
$PsCustomObject
)
process
{
$PSCmdlet.ParameterSetName
}
}
Piping [pscustomobject]
behaves as I expect:
PS C:\> New-Object pscustomobject | Test-Discrimination
pscustomobject
However, piping [string]
throws an exception:
PS C:\> 'string' | Test-Discrimination
Test-Discrimination : Parameter set cannot be resolved using the specified named parameters.
At line:1 char:12
+ 'string' | Test-Discrimination
+ ~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (string:String) [Test-Discrimination], Paramete
rBindingException
+ FullyQualifiedErrorId : AmbiguousParameterSet,Test-Discrimination
So does [hashtable]
:
PS C:\> @{} | Test-Discrimination
Test-Discrimination : Parameter set cannot be resolved using the specified named parameters.
At line:1 char:7
+ @{} | Test-Discrimination
+ ~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (System.Collections.Hashtable:Hashtable) [Test-
Discrimination], ParameterBindingException
+ FullyQualifiedErrorId : AmbiguousParameterSet,Test-Discrimination
Adding DefaultParameterSetName='hastable'
causes [hashtable]
but not [string]
to resolve correctly.
I'm not experienced at interpreting the output from Trace-Command. I did notice the output for [string]
includes this line:
BIND arg [string] to param [PsCustomObject] SUCCESSFUL
Which seems like PowerShell is considering [string]
to be a [PsCustomObject]
. But 'string' -is [pscustomobject]
evaluates to $false
.
This all leaves me with the following questions:
- Why can't PowerShell select a parameter set based on the difference in type between a
[string]
and a[pscustomobject]
? - Is the reason is that PowerShell considers a
[string]
to be a[pscustomobject]
? If so, why would that be? - Is there a workaround that allows me to use different types to select different parameter sets?