PowerShell: почему [Parameter (Mandatory = $ True)] для одного параметра влияет на поведение приведения типа другого параметра? - PullRequest
3 голосов
/ 07 октября 2019

Кто-нибудь знает, почему атрибут Mandatory для параметра $ a влияет на поведение приведения типа параметра $ b? В этом примере массив должен быть приведен к строке.

function test ([Parameter(Mandatory = $True)] [string] $a, [string] $b) {
  $a; $b
}
$b = "a", "b", "c"
test -a "my string" -b $b

Когда этот фрагмент кода выполняется, он выдает ошибку: test: Невозможно обработать преобразование аргумента для параметра 'b'. Невозможно преобразовать значение в тип System.String. В строке: 1 символ: 31

Если я удаляю атрибут Mandatory из $ a, он отлично работает:

function test ([string] $a, [string] $b) {
  $a; $b
}
$b = "a", "b", "c"
test -a "my string" -b $b

Заранее спасибо за отзыв

Ответы [ 2 ]

5 голосов
/ 07 октября 2019

Добавляя атрибут [Parameter()], вы подразумеваете атрибут [CmdletBinding()] (то есть превращаете функцию в Расширенную функцию ). Если вы посмотрите на исходный код для поведения при использовании [CmdletBinding()], вы увидите, что он явно запрещает преобразование массива в строку, что вы и пытаетесь сделать.

Чтобы увидеть, что он специфичен для массивов, попробуйте, например, $b = Get-Date (т.е. передать объект DateTime). Преобразование в строку работает отлично.

1 голос
/ 08 октября 2019

К дополнению полезный ответ boxdog :

Действительно, разница в поведении сводится к тому, является ли ваша функция простой (нет [CmdletBinding()] атрибута и / или [Parameter()] атрибутов) или продвинутый - подобный командлету - один.

Несмотря на очень полезные автоматические преобразования типов в PowerShell, можно поспоритьчто даже простые функции никогда не должны были позволять неявно преобразовывать массив в скалярное [string] значение параметра , потому что:

  • То, как массивы строковые (преобразованные в одну строку), несколько произвольно: по умолчанию , (строковые) элементы массива разделены пробел (блок сценария ({...}) без вышеупомянутых параметров по сути является простой функцией).

    • & { param([string] $s) "[$s]" } 'one', 'two' # -> '[one two]'
  • Более того, это поведение зависит от того, предпочтение $OFS vaДля параметра riable была задана произвольная строка-разделитель.

    • $OFS='!'; & { param([string] $s) "[$s]" } 'one', 'two' # -> '[one!two]'

Короче:

  • Было бы разумно всегда требовать преднамеренного преобразования массива , предназначенного для передачи параметру, который ожидает скаляр .

  • Однако, учитывая приверженность PowerShell к обратной совместимости, существующее поведение простых функций вряд ли изменится.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...