2015-05-17 16 views
4

PowerShell使用寫入時複製語義的內部作用域。PowerShell複製寫入行爲取決於操作員類型

這意味着如果您要更改內部範圍中的外部變量,那麼內部範圍將處理它自己的副本。這裏有一個例子:

$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 

這似乎是一個錯誤。唯一的問題是究竟在哪裏?我認爲在第二種情況下+=的行爲不正確。但也許我錯過了一些東西......

+0

我沒有證據表明這一點,但我認爲這裏的問題是什麼'+ ='解析成局部變量是什麼時候重新創建與何時被複制。在內部作用域中使用'$ list'會觸發'+ ='本身不包含的副本。這與作用域中變量的python行爲類似,以及作用域中稍後的賦值如何隱式地映射此範圍內較早使用的全局(由於提升)。 –

+0

但是爲什麼'+ ='與'New-Variable' cmdlet一起使用在方法的開頭?這種行爲上的差異就是一個bug。問題是:什麼是「正確的」行爲? –

+0

它可能會強制內部作用域的初始化,而'+ ='賦值並不是,但肯定是奇怪且令人困惑。在原來的閱讀中我錯過了這個區別。 –

回答

1

我在PowerShell 2.0中試過這3個測試。所有結果與第一次測試中的 相同。我還嘗試了標量值$list = 42以查看 問題是否特定於陣列。在v2中,所有測試都是相同的(45,45,45),在v3 中他們得到45,3,45。所以這個問題不僅僅是關於數組。

然後,我把在看在3.0重大更改,請參閱WMF 3發行Notes.docxWMF 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} 

根據該文件,在v3中,測試2是正確的,測試3顯示了一個錯誤。

更新:PowerShell 4.0與3.0相同。我沒有v5來測試這個。

+0

我將此問題添加到PowerShellTraps作爲[Compound -equality運營商](https://github.com/nightroman/PowerShellTraps/tree/master/Basic/Compound-equality-operators)。它使用兩個非常簡單的測試。 –

+0

此外,與發行說明相比,它看起來像'++'仍然使用動態範圍。爲上述PowerShellTraps添加了一個測試。 –

相關問題