PowerShell:为什么一个参数上的 [参数(必需 = $True)] 会影响另一个参数的类型转换行为?



有人知道为什么参数$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

如果我从$a中删除必需属性,它可以正常工作:

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

提前感谢您的反馈

通过添加[Parameter()]属性,您暗示了[CmdletBinding()]属性(即将函数转换为高级函数(。 如果您查看使用[CmdletBinding()]时行为的源代码,您会发现它明确禁止将数组转换为字符串,这就是您正在尝试做的事情。

要查看它特定于数组,请尝试例如$b = Get-Date(即传递DateTime对象(。 转换为字符串工作正常。

为了补充boxdog的有用答案:

事实上,行为的差异归结为您的函数是简单的函数(没有[CmdletBinding()]属性和/或[Parameter()]属性(还是高级的 - 类似 cmdlet 的 - 函数。

尽管 PowerShell 的自动类型转换通常非常有用,但您可能会争辩说,即使是简单的函数也不应该允许将数组隐式转换为标量[string]参数值,因为:

数组字符串化(
  • 转换为单个字符串(的方式有些任意:默认情况下,数组的(字符串(元素是空格分隔的(没有上述参数的脚本块({...}(实际上是一个简单的函数(。

    • & { param([string] $s) "[$s]" } 'one', 'two' # -> '[one two]'
  • 此外,此行为取决于$OFS首选项变量是否设置为任意分隔符字符串。

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

总之:

  • 始终要求故意转换要传递给需要标量的参数的数组是合理的。

  • 但是,鉴于PowerShell对向后兼容性的承诺,简单函数的现有行为不太可能改变。

最新更新