1

Consider the following code:

function Test
{
    [CmdletBinding()]
    param
    (
        [parameter(Mandatory=$true)]
        [AllowNull()]
        [String]
        $ComputerName
    ) 
    process{}
}

Test -ComputerName $null

Based on the official documentation for AllowNull I was expecting that $ComputerName could either be [string] or $null. However, running the above code results in the following error:

[14,24: Test] Cannot bind argument to parameter 'ComputerName' because it is an empty string.

Why doesn't passing $null for $ComputerName work in this case?

alx9r
  • 3,675
  • 4
  • 26
  • 55
  • I can't give you a definitive explanation, but to me it looks like `$null` is cast to an empty string, due to the parameter type, and thus isn't covered by the validation attribute anymore. Using `AllowEmptyString()` instead works. I'd consider this a documentation bug. – Ansgar Wiechers Aug 05 '15 at 22:09
  • [related](https://stackoverflow.com/q/45720150/1404637) – alx9r Aug 25 '17 at 15:02

3 Answers3

7

$null, when converted to [string], return empty string not $null:

[string]$null -eq $null # False
[string]$null -eq [string]::Empty # True

If you want to pass $null for [string] parameter you should use [NullString]::Value:

[string][NullString]::Value -eq $null # True
Test -ComputerName ([NullString]::Value)
user4003407
  • 21,204
  • 4
  • 50
  • 60
3

You also need to add the [AllowEmptyString()] attribute if you plan on allowing nulls and empty strings.

function Test
{
    [CmdletBinding()]
    param
    (
        [parameter(Mandatory=$true)]
        [AllowNull()]
        [AllowEmptyString()]
        [String]
        $ComputerName
    ) 
    process{}
}

Test -ComputerName $null
Aaron Jensen
  • 25,861
  • 15
  • 82
  • 91
0

As noted, when cast to a [string], $null becomes an empty string (""). To avoid this, one option is to type the param as an object - then in the body test first for $null, then check that $MyParam.GetType().Name is "String".