Можно ли связывать переменные вместе, чтобы очистить их? - PullRequest
1 голос
/ 26 октября 2019

Таким образом, можно очистить переменную с помощью командлета Clear-Variable, что соответствует значению $null.

Можно также удалить переменную с помощьюкомандлет Remove-Variable или командлет Remove-Item для переменных среды.

Мой вопрос заключается в том, чтобы связать переменные вместе следующим образом ...

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

... законный способ очистки переменных или даже присвоения значений?

Я знаю, что $var1 не зависит от $var2, еслиВы присваиваете значения следующим образом: $var1 = $var2 = 1, но когда значение является объектом, созданным с помощью командлета New-Object, обе переменные указывают на один и тот же объект:

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

Этотолько вниз значение, равное Microsoft .NET Framework или COM object?

1 Ответ

4 голосов
/ 26 октября 2019

... законный способ очистки переменных

Да, что-то вроде $var1 = $var2 = $null (использовать только 2 переменных какпример) является законным способом очистки значений переменных, при условии, что целевые переменные (переменные) фактически определены в локальной (текущей) области действия.

Если они просто видны из родительской (наследственной) области видимости, вы случайно создадите локальных переменных с тем же именем, значение которых $null -см. этот ответ .

То же самое относится к Clear-Variable var1, var2 в принципе, за исключением того, что оно выдаст ошибку , если нет локальная переменная (и) $var1 и $var2 определены;кроме того, Clear-Variable позволяет явно нацеливаться на другую область с помощью -Scope.

. С ограничениями вы также можете назначать другие области с помощью переменных, используя спецификаторы области, такие как $script:var - см. этот связанный ответ .

Remove-Variable действует аналогично Clear-Variable и также поддерживает -Scope, но действительно удаляет (undefines) переменных из подразумеваемой или целевой области.

Обратите внимание, что доступ к удаленной / несуществующей переменной по умолчанию по сути аналогичен доступу к существующей переменной со значением $null. Однако при действии Set-StrictMode -Version 1 или выше доступ к несуществующей переменной не выполняется по проекту.

$var1 = $var2 = $null имеет следующие преимущества по сравнению с Clear-Variable var1, var2:

  • Это более лаконично, а также быстрее (вызов командлета не требуется).
  • Может использоваться для неявного создания переменных со значением $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 пытается преобразовать $null в заблокированный тип, что может иметь два результата:

  • Преобразование завершается успешно, и в этом случае преобразованное значение заблокированного типа является новым значением;например, в случае [int] это значение равно 0, поскольку [int] $null равно 0.

    [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 и присвоения ненулевое значение для нескольких переменных:

Как указано в комментариях, результирующее поведение сводится к тому, является ли тип-значения экземпляромили тип ссылки назначается экземпляр [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] технически ссылочный тип, но имеет семантику value -типа, чтобы обеспечить более интуитивную обработку строк - см. этот ответ .

New-Object способен создавать экземпляры любого типа: если вы дадите ему имя типа значения, вы получите экземпляр типа значения;учитывая имя ссылочного типа, вы получите экземпляр ссылочного типа.

Однако, учитывая, что встроенные типы значений могут быть созданы с помощью литералов (например, 1) или простых приведений ([int]), New-Object чаще используется для создания ссылоктипов.


[1] Учитывая тип или экземпляр, вы можете проверить свойство .IsValueType типа, чтобы определить, является ли он типом значения или нет;например, потому что [int] (System.Int32) является типом значения [int].IsValueType и (1).GetType().IsValueType yield $true, тогда как [System.IO.FileInfo].IsValueType равен $false, поскольку последний является ссылочным типом.

...