0

Why does a [string] casted parameter with the 'value' $null in this example never throw an error (empty or $null), but a string with the value '$null' always throws? I would expect if passing a mandatory parameter, it is checked for $null/emptyness and thus an error is always thrown in these cases:

Function test_M_NoE ( [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [string] $x ) {}

# test cases. Uncomment one:
[string]$x = [string]$null 
# $x = [string]$null
# [string]$x = $null
# $x = $null 

"1:"; test_M_NoE [string]$x # never error
"2:"; test_M_NoE $x         # always error
4
  • Converting $null to [string] in PowerShell results in an empty string (eg. "" or [String]::Empty), so the argument passed is never actually $null once you cast to [string]. But in your case, [string]$x is not an actual cast expression - it's parsed in argument mode, and interpreted as an expandable string, eg. no different that test_M_NoE "[string]$x" Commented Sep 20, 2021 at 12:05
  • @MathiasR.Jessen Ok, but an empty string should also throw (ValidateNotNullOrEmpty) and it always does in the last statement. Why not if I cast the parameter? Commented Sep 20, 2021 at 12:09
  • The expression "[string]$null" results in a non-empty string Commented Sep 20, 2021 at 12:09
  • $x = [string]$null; test_M_NoE $x yields an error. What's the difference? Commented Sep 20, 2021 at 12:11

1 Answer 1

2

The reason this works:

test_M_NoE [string]$x

Is that [string]$x is not being interpreted the way you expect.

Let's change your test function definition to help us better see what's actually going on:

function test_M_NoE {
  param(
    [Parameter(Mandatory=$true)]
    [ValidateNotNullOrEmpty()]
    [string]$x
  )

  Write-Host "Argument value passed was: '$x'"
}

Now, let's try again:

PS ~> $x = $null
PS ~> test_M_NoE [string]$x
Argument value passed was: '[string]'

Aha! The argument expression [string]$x did not result in an empty string - it resulted in the literal string value [string].

This is due to the fact that PowerShell attempts to parse command arguments differently from anything else. From the about_Parsing help topic:

Argument mode is designed for parsing arguments and parameters for commands in a shell environment. All input is treated as an expandable string unless it uses one of the following syntaxes: [...]

So really, PowerShell interprets our argument expression like a double-quoted string:

test_M_NoE "[string]$x"

At which point the behavior makes sense - $x is $null, so it evaluates to an empty string, and the result of the expression "[string]$x" is therefore just [string].

Enclose the argument expression in the $(...) subexpression operator to have it evaluated as a value expression instead of as an expandable string:

test_M_NoE $([string]$x)
Sign up to request clarification or add additional context in comments.

2 Comments

That makes sense now, thank you. To me very unexpected though. So as a consequence I suppose one should not cast function parameters at all and always make sure the parameter already has got the correct type, true?
@jamacoe no, not at all. My recommendation would be: don't do anything - PowerShell will automatically attempt to convert/coerce the argument to the target type, so your attempts at manually converting the argument to [string] explicitly is completely unnecessary.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.