Powershell - 函数和循环中的变量范围

Powershell - variable scope in function and loop

考虑以下几点:

function GetOneOf($prompt, $values) {
    $response=
    while ($response -eq $null) {
        $response = read-host $prompt
        if ( -not ($values -icontains $response)) {
            $response = $null
        }
    }
    $response
}

function GetOneOfV2($prompt, $values) {
    # "$response=" fragment is missing
    while ($response -eq $null) {
        $response = read-host $prompt
        if ( -not ($values -icontains $response)) {
            $response = $null
        }
    }
    $response
}

$resp = GetOneOf 'enter A or B' 'a', 'b'
write-host "RESP: $resp"
$resp = GetOneOfV2 'enter A or B' 'a', 'b'
write-host "RESP: $resp"

为什么GetOneOf没有return输入值而GetOneOfV2return呢?我看不出有任何理由以这种方式工作。如果第一种情况 (GetOneOf) 以这种方式工作,因为 while 构成另一个范围并且变量不能在那里更改,那么 OK,但如果是这样,那么在第二种情况下应该没有办法读取值$response in scope outside loop 因为之前没有这样的变量。事实上我应该得到 no such variable 或类似的错误。但是如果我们假设循环内部的变化在外部可见(第二种情况)并且它们甚至使变量可用于外部范围,那么第一种情况怎么可能不起作用?

还有我怎样才能使第一个案例 (GetOneOf) 起作用?

我使用以下:

Name                           Value
----                           -----
PSVersion                      5.1.19041.1237
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.19041.1237
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1

它与变量作用域无关,您将 while 的 return 值分配给 $response,它总是 null 因为您 return 没什么。

这里应该可以工作:

function GetOneOf($prompt, $values) {
    $response=
    while ($response -eq $null) {
        $response = read-host $prompt
        if ( -not ($values -icontains $response)) {
            $response = $null
        } else {
            echo $response
        }
    }
    $response
}

输出:

PS C:\> $resp = GetOneOf 'enter A or B' 'a', 'b'
enter A or B: d
enter A or B: f
enter A or B: g
enter A or B: w
enter A or B: a
PS C:\> $resp
a
PS C:\> $resp.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     String                                   System.Object