我知道 Powershell 数组是不可变的对象,并且像所有对象一样,通过引用函数来传递。但是我在下面的例子中不明白为什么$b没有与$a.
唯一的区别是它$b不是强类型的。这是否意味着从toTest-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
Run Code Online (Sandbox Code Playgroud)
输出:
Modified by Test-ByRefArray, world
hello, world
Modified by Test-ByRefArray, world
Run Code Online (Sandbox Code Playgroud)
这里发生的情况是,类型$a满足 的类型约束$Array1- 它已经是 a [string[]],并且 PowerShell 按原样将它传递给您的函数 - 所以$Array1现在持有对与在调用站点具有引用完全相同的数组$a的引用。
$b,在另一方面,隐式类型[object[]]-并[object[]]没有未满足类型约束[string[]]上$Array2:
PS ~> [string[]].IsAssignableFrom([object[]])
False
Run Code Online (Sandbox Code Playgroud)
由于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
Run Code Online (Sandbox Code Playgroud)
输出起初可能看起来有点混乱,但在这里我们可以看到 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
Run Code Online (Sandbox Code Playgroud)
在此,另一方面,我们看到的PowerShell创建新阵列(倒数第三调试语句),然后结合该来$ParamArray。
| 归档时间: |
|
| 查看次数: |
53 次 |
| 最近记录: |