#powershell #validation #parameters #casting
Вопрос:
Почему приведенный параметр [string] со значением «$null «в этом примере никогда не выдает ошибку (пустую или $null), но строка со значением «$null» всегда выдает ошибку? Я бы ожидал, что при передаче обязательного параметра он проверяется на наличие $null/пустоты, и поэтому в этих случаях всегда возникает ошибка:
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
Комментарии:
1. Преобразование
$null
в[string]
в PowerShell приводит к пустой строке (например,""
или[String]::Empty
), поэтому переданный аргумент на самом деле никогда$null
не используется после приведения[string]
. Но в вашем случае[string]$x
это не фактическое приведенное выражение — оно анализируется в режиме аргумента и интерпретируется как расширяемая строка, например. ничем не отличается от этогоtest_M_NoE "[string]$x"
2. @MathiasR.Jessen Хорошо, но пустая строка также должна выдавать (ValidateNotNullOrEmpty), и это всегда происходит в последнем операторе. Почему бы и нет, если я приведу параметр?
3. Выражение
"[string]$null"
приводит к непустой строке4. $x = [строка]$null; test_M_NoE $x выдает ошибку. В чем разница?
Ответ №1:
Причина, по которой это работает:
test_M_NoE [string]$x
Это то, что [string]$x
интерпретируется не так, как вы ожидаете.
Давайте изменим определение вашей тестовой функции, чтобы помочь нам лучше понять, что происходит на самом деле:
function test_M_NoE {
param(
[Parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string]$x
)
Write-Host "Argument value passed was: '$x'"
}
А теперь давайте попробуем еще раз:
PS ~> $x = $null
PS ~> test_M_NoE [string]$x
Argument value passed was: '[string]'
Ага! Выражение аргумента [string]$x
не привело к пустой строке — оно привело к буквальному строковому значению [string]
.
Это связано с тем, что PowerShell пытается анализировать аргументы команд иначе, чем что-либо другое. Из раздела about_Parsing
справки:
Режим аргументов предназначен для анализа аргументов и параметров команд в среде командной оболочки. Все входные данные обрабатываются как расширяемая строка, если только в ней не используется один из следующих синтаксисов: […]
Так что на самом деле PowerShell интерпретирует наше выражение аргумента как строку в двойных кавычках:
test_M_NoE "[string]$x"
В этот момент поведение имеет смысл — $x
есть $null
, поэтому оно оценивается как пустая строка, и поэтому результат выражения "[string]$x"
является справедливым [string]
.
Заключите выражение аргумента в оператор $(...)
подвыражения, чтобы оно оценивалось как выражение значения, а не как расширяемая строка:
test_M_NoE $([string]$x)
Комментарии:
1. Теперь это имеет смысл, спасибо. Хотя для меня это было очень неожиданно. Поэтому, как следствие, я полагаю, что вообще не следует приводить параметры функции и всегда убеждаться, что параметр уже имеет правильный тип, верно?
2. @jamacoe нет, вовсе нет. Моя рекомендация была бы такой: ничего не делайте — PowerShell автоматически попытается преобразовать/принудить аргумент к целевому типу, поэтому ваши попытки вручную преобразовать аргумент в
[string]
явное совершенно не нужны.