Powershell数组、函数和引用



我知道Powershell数组是不可变的对象,和所有对象一样,是通过引用传递给函数的。但在下面的例子中,我不明白为什么$b的值与$a的值不同。

唯一的区别是$b不是强类型的。这是否意味着Test-ByRefArray$b[object[]]转换为[string[]],实际上创建了一个新对象,这可以解释为什么Test-ByRefArray对这个新对象所做的更改对原始对象没有影响?

function Test-ByRefArray {
param (
[string[]] $Array1,
[string[]] $Array2
)
$Array1[0] = "Modified by Test-ByRefArray"
$Array2[0] = "Modified by Test-ByRefArray"
}
function Test-Array {
[string[]] $a = 'hello', 'world'
$b = 'hello', 'world'
$c = $a #by ref: if a is updated, so is $c
Test-ByRefArray -Array1 $a -Array2 $b
$a -join ", "
$b -join ", "
$c -join ", "
}
Test-Array

输出:

Modified by Test-ByRefArray, world
hello, world
Modified by Test-ByRefArray, world

这里发生的情况是,$a的类型满足$Array1的类型约束-它已经是[string[]],PowerShell按原样将其传递给您的函数-因此$Array1现在拥有对数组的引用,与$a在调用站点拥有对其的引用完全相同。

另一方面,$b是隐式类型的[object[]]-并且[object[]]不满足$Array2:上的类型约束[string[]]

PS ~> [string[]].IsAssignableFrom([object[]])
False

由于PowerShell希望提供帮助,它将数组转换为新的[string[]],因此$Array2引用了在参数绑定过程中创建的这个新数组。

因此,$b引用的数组的内容永远不会被修改——$Array2引用的是一个完全不同的数组。


我们可以在Windows PowerShell 5.1:中观察Trace-Command的输出中是否发生类型转换(或类型强制(

PS ~> Trace-Command -Expression {&{param([string[]]$ParamArray)} @([string[]]@())} -Name ParameterBinding -PSHost
DEBUG: ParameterBinding Information: 0 : BIND arg [System.String[]] to parameter [ParamArray]
DEBUG: ParameterBinding Information: 0 :     Executing DATA GENERATION metadata: [System.Management.Automation.ArgumentTypeConverterAttribute]
DEBUG: ParameterBinding Information: 0 :         result returned from DATA GENERATION: System.String[]
DEBUG: ParameterBinding Information: 0 :     BIND arg [System.String[]] to param [ParamArray] SUCCESSFUL

输出一开始可能看起来有点混乱,但在这里我们可以看到PowerShell使用$ParamArray参数的类型约束,并确定输入参数的类型已经是[string[]]——不需要实际工作。

现在让我们传递一个隐式类型的数组:

PS ~> Trace-Command -Expression {&{param([string[]]$ParamArray)} @(@())} -Name ParameterBinding -PSHost
DEBUG: ParameterBinding Information: 0 : BIND arg [System.Object[]] to parameter [ParamArray]
DEBUG: ParameterBinding Information: 0 :     Executing DATA GENERATION metadata: [System.Management.Automation.ArgumentTypeConverterAttribute]
DEBUG: ParameterBinding Information: 0 :         result returned from DATA GENERATION: System.Object[]
DEBUG: ParameterBinding Information: 0 :     Binding collection parameter ParamArray: argument type [Object[]], parameter type [System.String[]], collection type Array, element type [System.String], no coerceElementType
DEBUG: ParameterBinding Information: 0 :     Arg is IList with 0 elements
DEBUG: ParameterBinding Information: 0 :     Creating array with element type [System.String] and 0 elements
DEBUG: ParameterBinding Information: 0 :     Argument type System.Object[] is IList
DEBUG: ParameterBinding Information: 0 :     BIND arg [System.String[]] to param [ParamArray] SUCCESSFUL

另一方面,在这里,我们看到PowerShell创建了一个新数组(倒数第三条调试语句(,然后将绑定到$ParamArray

最新更新