Потратил немного копаться в этом, и это то, что я наблюдал.
Во-первых, для ясности, я не верю, что вы должны рассматривать значение NullString как нулевое в базовом сравнении.Не уверен, зачем вам это нужно, так как обычно это то, что я ожидаю от разработки на c #.Вы должны иметь возможность просто использовать $null
для большей части работы в PowerShell.
if($null -eq [System.Management.Automation.Language.NullString]::Value)
{
write-host "`$null -eq [System.Management.Automation.Language.NullString]::Value"
}
else
{
write-host "`$null -ne [System.Management.Automation.Language.NullString]::Value"
}
Во-вторых, проблема не обязательно связана с оператором вызова, то есть &
.Я считаю, что вместо этого вы имеете дело с принудительным привязыванием параметров.Строгая типизация данных, безусловно, является слабой областью для PowerShell, так как даже явно объявленный [int]$val
может в конечном итоге установить PowerShell для строкового типа автоматически в следующей строке при записи Write-Host $Val
.
Чтобы определить основнойВ своем поведении я использовал функцию Trace-Command
( Trace Command ).
Я изменил Use-Dot, чтобы просто вызывать функцию, поскольку для вывода строки не требовался хост записи.
function Use-Ampersand
{
param(
[string]$NullString = [System.Management.Automation.Language.NullString]::Value
)
Format-Type $NullString
&cmd.exe /c exit 0
}
Формат-Type I был изменен, чтобы также использовать то, что считаетсялучшая практика $null
слева, опять же из-за вывода типа.
function Format-Type($v= [System.Management.Automation.Language.NullString]::Value)
{
if ($null -eq $v)
{
'(null)'
}
else {
$v.GetType().FullName
}
}
Чтобы сузить проблему с типами данных, я использовал следующие команды, хотя это не то, где я нашел понимание проблемы.Оба при вызове напрямую работали одинаково.
Trace-Command -Name TypeConversion -Expression { Format-Type $NullString} -PSHost
Trace-Command -Name TypeConversion -Expression { Format-Type ([System.Management.Automation.Language.NullString]$NullString) } -PSHost
Однако, когда я запустил функции с использованием трассировки TypeConversion, он показал разницу в конверсиях, что, вероятно, объясняет некоторые из ваших наблюдаемых действий.
Trace-Command -Name TypeConversion -Expression { Use-Dot} -PSHost
Trace-Command -Name TypeConversion -Expression { Use-Ampersand} -PSHost
# USE DOT
DEBUG: TypeConversion Information: 0 : Converting "" to "System.String".
DEBUG: TypeConversion Information: 0 : Converting object to string.
DEBUG: TypeConversion Information: 0 : Converting "" to "System.Object". <<<<<<<<<<<
DEBUG: TypeConversion Information: 0 : Converting ".COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC;.PY;.PYW;.CPL" to "System.String".
DEBUG: TypeConversion Information: 0 : Result type is assignable from value to convert's type
OUTPUT: (null)
# Use-Ampersand
DEBUG: TypeConversion Information: 0 : Converting "" to "System.String".
DEBUG: TypeConversion Information: 0 : Converting object to string.
DEBUG: TypeConversion Information: 0 : Converting "" to "System.String". <<<<<<<<<<<
DEBUG: TypeConversion Information: 0 : Converting null to "". <<<<<<<<<<<
DEBUG: TypeConversion Information: 0 : Converting ".COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC;.PY;.PYW;.CPL" to "System.String".
DEBUG: TypeConversion Information: 0 : Result type is assignable from value to convert's type
OUTPUT: System.String
Заметная разница в Use-Ampersand
, это показывает утверждение Converting null to ""
против Converting "" to "System.Object"
.В PowerShell $null <> [string]''
.Сравнение пустой строки пройдет проверку на ноль, что приведет к успешному выводу GetType()
.
Несколько мыслей о подходе с PowerShell
Почему это происходит, я не уверен,но прежде чем уделять больше времени исследованиям, позвольте мне дать один совет, основанный на изучении трудного пути.
Если вы начнете решать проблемы из-за попыток принудительного использования типов данных в PowerShell, сначала подумайте, есть ли PowerShellэто правильный инструмент для работы
Да, вы можете использовать расширения типа.Да, вы можете использовать типы данных .NET, такие как $List = [System.Collections.Generic.List[string]]::new()
, и могут применяться некоторые типизированные правила .NET.Однако PowerShell не предназначен для строго типизированного языка, такого как C #.Попытка приблизиться к нему таким образом приведет к множеству трудностей.Несмотря на то, что я большой поклонник PowerShell, я научился понимать, что его гибкость следует ценить, а ограничения - уважать.
Если бы у меня действительно были проблемы, которые требовали столь сильного сопоставления [System.Management.Automation.Language.NullString]::Value
, я бы рассмотрел свой подход.
Тем не менее, это было сложное расследование, в котором я должен был принять участие, предоставив при этом свои 10 центов.
Другие ресурсы
После публикации моего ответа я нашел еще один ответ , который показался мне уместным, а также поддерживает упоминание о том, что [NullString]
не используется как обычный способ использования.в PowerShell не совсем то, для чего он был разработан.