为什么 Trap 块内的变量赋值在其外部不可见?

Sco*_*nro 4 powershell

为什么我在 Trap 块内进行的变量分配在其外部不可见?

$integer = 0;
$string = [String]::Empty;
$stringBuilder = new-object 'System.Text.StringBuilder';

trap
{
    $integer = 1;
    $string = '1';
    $stringBuilder.Append('1');

    write-host "Integer Variable Inside: " $integer;
    write-host "String Variable Inside: " $string;
    write-host "StringBuilder Variable Inside: " $stringBuilder;

    continue;
}
$dummy = 1/$zero;

write-host "Integer Variable Outside: " $integer;
write-host "String Variable Outside: " $string;
write-host "StringBuilder Variable Outside: " $stringBuilder;
Run Code Online (Sandbox Code Playgroud)

我本以为 Trap 块内部和外部的结果是相同的,但这些是我看到的结果。

Integer Variable Inside:  1
String Variable Inside:  1
StringBuilder Variable Inside:  1
Integer Variable Outside:  0
String Variable Outside:
StringBuilder Variable Outside:  1
Run Code Online (Sandbox Code Playgroud)

请注意,只有 StringBuilder 保留其值。

我猜测这与值类型和引用类型之间的差异有关,但不能完全确定。

Sco*_*nro 5

根据上面slipsec 提供的信息并通过一些进一步的实验,我现在明白这里发生了什么。

\n\n

Joel解释了Trap 范围的工作原理如下。

\n\n
\n

即使在我们的错误处理程序中,我们能够访问 $Result 的值,并看到它是 True \xe2\x80\xa6 和 \n 即使我们将其设置为 $False,并将其打印出来所以你可以看到\n设置\xe2\x80\xa6该函数仍然返回True,\n因为陷阱范围不会\n\xe2\x80\x99t修改\n外部范围,除非你\n显式设置a的范围\n 变量。注意:如果您使用\n $script:result 而不是$result(在该脚本中\n $result 出现的每个实例中),您将获得字符串/注释引导您的\n 输出预计。

\n
\n\n

因此,可以读取 Trap 范围之外的变量,但不能设置它们,因为它们是原始变量的副本(感谢Jason)。这就是 Integer 变量没有保留其值的原因。然而,StringBuilder 是一个引用对象,而变量只是指向该对象的指针。Trap 范围内的代码能够读取变量设置的引用并修改它所指向的对象 - 变量本身不需要更改。

\n\n

请注意,Joel 关于指定变量范围的提示允许我在 Trap 范围内设置 Integer 变量的值。

\n\n

$script:integer = 0;\n$string = [String]::Empty;\n$stringBuilder = new-object \'System.Text.StringBuilder\';

\n\n
trap\n{\n    $script:integer = 1;\n    $string = \'1\';\n    $stringBuilder.Append(\'1\');\n\n    write-host "Integer Variable Inside: " $script:integer;\n    write-host "String Variable Inside: " $string;\n    write-host "StringBuilder Variable Inside: " $stringBuilder;\n    continue;\n}\n$dummy = 1/$zero;\n\nwrite-host "Integer Variable Outside: " $script:integer;\nwrite-host "String Variable Outside: " $string;\nwrite-host "StringBuilder Variable Outside: " $stringBuilder;\n
Run Code Online (Sandbox Code Playgroud)\n\n

......这些是结果。

\n\n
Integer Variable Inside:  1\nString Variable Inside:  1\nStringBuilder Variable Inside:  1\nInteger Variable Outside:  1\nString Variable Outside:\nStringBuilder Variable Outside:  1\n
Run Code Online (Sandbox Code Playgroud)\n\n

请注意,字符串变量不会保留其值,因为虽然它是引用类型,但它也是不可变的。

\n

  • 是的,您对 String 变量的怀疑是正确的。另外,更准确的说法是 Trap 作用域继承了所有变量的副本。因此它会针对自己的副本进行读取和写入。 (3认同)