写入行为的PowerShell副本取决于运算符类型

时间:2015-05-17 18:28:52

标签: powershell

PowerShell对内部范围使用copy-on-write语义。

这意味着如果您在内部范围内更改外部变量,那么内部范围将处理它自己的副本。这是一个例子:

$list = @(1, 2)

Function Foo
{
  "Foo: initial value - $list"
  $list = $list + 3
  "Foo: `$list: $list, `$global:list: $global:list"  
}

输出结果为:

Foo: initial value - 1 2
Foo: $list: 1 2 3, $global:list: 1 2

好的,这种行为是设计的。但是让我们改变Foo函数:

Function Foo
{
  "Foo: initial value - $list"
  $list += 3
  "Foo: `$list: $list, `$global:list: $global:list"  
}

输出结果为:

Foo: initial value - 1 2
Foo: $list: 3, $global:list: 1 2

嗯...我可以假设x += y运算符与x = x + y不完全相同。但这并没有被解决。让我们再次更改代码:

Function Foo
{
  New-Variable -Name z -Value 42
  "Foo: initial value - $list"
  $list += 3
  "Foo: `$list: $list, `$global:list: $global:list"  
}

现在的输出是:

Foo: initial value - 1 2
Foo: $list: 1 2 3, $global:list: 1 2

这似乎是一个错误。唯一的问题是究竟在哪里?我假设在第二种情况下+=的行为是不正确的。但也许我错过了一些东西......

1 个答案:

答案 0 :(得分:1)

我在PowerShell 2.0中尝试了这3个测试。所有结果都与中的相同 第一次测试。我还尝试了标量值$list = 42以查看是否有 问题特定于数组。在v2中,所有测试都是相同的(45,45,45),在v3中 他们得到45,3,45。所以问题不仅仅是数组。

然后我看了一下v3.0中的变化,请参阅 WMF 3发行说明.docx WMF 3.0

该文件说:

更改

Read/Modify/Write operators no longer use dynamic scoping for the Read
operation. Also, compound equality operators (including +=, -=, *=, %=, ++,
--) do not use dynamic scoping.  The variable is always in the current scope.

样品

$x = 1
& { $x += 1; $x }
# Returns 2 in Windows PowerShell 2.0
# Returns 1 in Windows PowerShell 3.0

错误消息

No error. Results differ.

解决方法

Rewrite to use only the simple assignment operator:
$x = 1
& { $x = $x + 1; $x}

根据该文件,在第3版中,测试2是正确的,测试3显示了错误。

更新:PowerShell 4.0与3.0相同。我没有v5来测试它。