... законный способ очистки переменных
Да, что-то вроде $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
, поскольку последний является ссылочным типом.