可以将变量串在一起以清除它们吗?

Is it ok to string variables together to clear them?

因此,可以使用 Clear-Variable cmdlet 清除变量,这与给它赋值 $null.

是一样的

也可以使用环境变量的 Remove-Variable cmdlet or the Remove-Item cmdlet 删除变量。

我的问题是,像这样将变量串在一起...

$Env:var1 = $var2 = $var3 = $null

...清除变量甚至赋值的合法方法?

我知道 $var1 独立于 $var2 如果您像这样分配值:$var1 = $var2 = 1,但是当该值是使用 New-Object cmdlet 创建的对象时,两个变量都指向同一个对象:

$var1 = $var2 = New-Object System.Diagnostics.Stopwatch
$var1.Start()
Start-Sleep 1
$var2.Stop()
Start-Sleep 1
$var1.Elapsed.TotalMilliseconds

这仅仅是降低了 Microsoft .NET FrameworkCOM object 的价值吗?

... a legitimate way of clearing variables

是的,像 $var1 = $var2 = $null(以 2 变量为例)是 清除变量值的合法方法,前提是目标变量实际上是 definedlocal(当前)范围内。

如果它们仅在 parent(祖先)范围内可见,您将无意中创建同名的 local 变量其值为 $null - 参见 .

原则上同样适用于Clear-Variable var1, var2,除了它会发出错误如果没有local 变量 $var1$var2 已定义;此外,Clear-Variable 允许使用 -Scope.

明确定位不同的范围

有限制,您还可以使用范围说明符(例如 $script:var)将其他范围作为变量赋值的目标 - 参见 .

Remove-VariableClear-Variable 类似,也支持 -Scope,但真正 删除 (取消定义)来自隐含或目标范围的变量。

请注意,默认情况下访问已删除/不存在的变量与访问值为$null的现有变量实际上是一样的。 但是,在 Set-StrictMode -Version 1 或更高版本的情况下,访问不存在的变量会在设计上失败。

$var1 = $var2 = $null相对于Clear-Variable var1, var2有以下优点:

  • 它更简洁,也更快(不需要调用 cmdlet)。
  • 它可以用于隐式地 创建 具有 $null 值的变量,或者,换句话说,如果其中一个变量,语句不会失败不存在。
  • 它也可以与环境变量一起使用(例如,$env:FOO),但请注意分配$null(或'',空字符串)到环境变量实际上 删除 它们($env:FOO = $null 等同于 Remove-Item Env:FOO)。

警告:

赋值$null或调用Clear-Variable不一定导致变量包含$null:

变量可能是类型约束,,在这种情况下,它们只允许存储在创建(初始化)时锁定的类型的值时间:

[int] $i = 1  # Create a type-constrained variable that can only store [int] values.

当您将 $null 分配给类型受限变量时,PowerShell 会尝试 convert $null 为锁定类型,该类型可以有两个结果:

  • 转换成功,此时锁定类型的converted值为新值;例如,在 [int] 的情况下,该值是 0,因为 [int] $null0.

    [int] $i = 1; $i = $null; $i # -> 0, not $null
    
  • 转换可能失败,导致错误;在 [datetime] 的情况下,转换失败,因为 [datetime] $null 失败。

    # !! ERROR: Cannot convert null to type "System.DateTime"
    [datetime] $dt = Get-Date; $dt = $null 
    

至于New-Object并且给多个变量赋一个非空值:

如评论中所述,结果行为归结为是否分配了 value-type instance or a reference-type 实例[1]:

  • 使用值类型实例,每个变量都有自己的值的独立副本

    # A value-type instance such as an [int] instance assigns
    # *independent copies* of itself to the target variable(s):
    $var1 = $var2 = 42; $var2 = 43; $var1, $var2 # -> 42, 43
    
  • 使用引用类型实例,所有变量真正引用同一个对象

    # A reference-type instance such as a [hashtable] instance assigns
    # a *reference to itself* to the target variable(s), which therefore
    # all reference the same object.
    $var1 = $var2 = @{one=1}; $var2.one = 2; $var1.one, $var2.one # -> 2, 2
    

请注意,[string] 实例是一个例外[string] 在技术上是一个 reference 类型,但展示value-type 语义,以提供更直观的字符串处理 - 参见 this answer.

New-Object 可以实例化任何一种类型:如果你给它一个值类型的名字,你会得到一个值类型的实例;给定引用类型的名称,您将获得一个引用类型实例。

但是,鉴于内置值类型可以用文字(例如,1)或简单的强制转换([int])实例化,New-Object更通常用于实例化引用类型。


[1] 给定类型或实例,您可以检查类型的 .IsValueType 属性 以确定它是否是值类型;例如,因为 [int] (System.Int32) 是一个值类型 [int].IsValueType 并且 (1).GetType().IsValueType 产生 $true,而 [System.IO.FileInfo].IsValueType$false,因为后者是引用类型。