考虑以下 PowerShell 代码:
> $null -gt 0
False
> $null -ge 0
False
> $null -eq 0
False
> $null -le 0
True
> $null -lt 0
True
Run Code Online (Sandbox Code Playgroud)
当然,对于显式设置为$null
或不存在变量的 $variable 也是如此。
$null
?或者这些方法之一被认为是非常标准的?谢谢你的时间。如果这个问题对这个场地来说太“模糊”,请提前道歉。
PS我通常的环境是PowerShell v5.1。
\n\n这是为什么?
\n
这种行为是违反直觉的:
\n运算符-lt
, -le
, -gt
, -ge
,尽管它们也可以具有数字含义,但似乎将$null
操作数视为空字符串(\'\'
),即它们默认为string Comparison ,正如postanote\'s 有用答案中的示例命令所暗示的那样。
也就是说,$null -lt 0
实际上 的计算结果与 相同\'\' -lt \'0\'
,这解释了$true
结果,因为在词法比较中满足了条件。\n虽然您也可以这样
想,但情况很特殊- 见下文。$null -eq 0
\'\' -eq \'0\'
-eq
此外,将 放在LHS0
上仍然起到字符串比较的作用(除非见下文) - 尽管通常是 LHS 的类型导致 RHS 被强制为相同的类型-eq
。
也就是说,0 -le $null
太似乎表现得像\'0\' -le \'\'
,因此返回$false
。
虽然这种行为在完全基于字符串的运算符(例如-match
and )中是预料之中的,但对于也支持数字-like
的运算符来说,这是令人惊讶的,特别是考虑到其他此类运算符 - 以及那些完全基于数字的运算符 - 默认为数字解释的$null
, 作为0
.
+
、-
和/
do强制 LHS (默认情况$null
下);例如是0
[int]
$null + 0
0
*
才不是; 例如,$null * 0
又是$null
。其中,-
和完全/
是数字,而和也可以在字符串和数组上下文中使用。+
*
还有一个额外的不一致:-eq
从不$null
对操作数执行类型强制:
$null -eq <RHS>
仅当$true
is <RHS>
is$null
(或“自动化 null” - 见下文)时才为 ,并且是目前可靠地测试 being 值的唯一方法$null
。(换句话来说:与-此处不发生类型强制$null -eq \'\'
不同。)\'\' -eq \'\'
$null
,例如<LHS> -is $null
.同样,<LHS> -eq $null
也不执行任何类型强制,$null
并且$true
仅返回$null
LHS;
<LHS>
,-eq
充当过滤器(就像大多数运算符所做的那样),返回元素的子数组$null
;例如,1, $null, 2, $null, 3 -eq $null
返回 2 元素数组$null, $null
。$null -eq <RHS>
这种过滤行为是只有- 作为$null
标量 LHS - 作为 (标量) 的测试是可靠的原因$null
。请注意,这些行为同样适用于PowerShell 用于表达命令(技术上讲,[System.Management.Automation.Internal.AutomationNull]::Value
单例)的(非)输出的“自动化 null”值,因为该值的处理方式与表达式$null
中的相同;例如也是- 请参阅此答案以获取更多信息。$(& {}) -lt 0
$true
同样,这些行为也适用于恰好包含(例如,也是)的可空值类型的实例,谢谢,D\xc3\xa1vid Laczk\xc3\xb3。,但请注意,它们在 PowerShell 中的使用很少。$null
[System.Nullable[int]] $x = $null; $x -lt 0
$true
\n\n这个结果可以而且应该被依赖吗?
\n
由于操作员之间的行为不一致,因此我不会依赖它,尤其是因为也很难记住何时应用哪些规则 - 并且至少有一个假设的机会可以修复不一致的情况;然而,考虑到这将构成重大改变,这种情况可能不会发生。
\n如果不考虑向后兼容性,则以下行为将消除不一致并制定易于概念化和记住的规则:
\n当(本质上是标量)二元运算符被赋予一个$null
操作数和一个非$null
操作数时 - 无论哪一个是左侧,哪个是右侧:
对于专门对数字/布尔/字符串操作数进行操作的运算符(例如// /
):将操作数强制为运算符隐含的类型。-and
-match
$null
对于在多个“域”中操作的运算符- 文本和数字(例如-eq
) - 将$null
操作数强制为另一个操作数的类型。
请注意,这还需要$null
使用不同语法进行专门测试,例如-is $null
上述 PR 中的 。
注意:上面的内容不适用于集合运算符-in
and -contains
(以及它们的否定变体-notin
and -notcontains
),因为它们的元素相等比较的行为类似于-eq
,因此永远不会对$null
值应用类型强制。
\n\n可靠地测试可能值为 $null 的变量中的整数值(或其他类型)的最佳(即最简洁、性能最佳等)方法是什么?
\n
以下解决方案强制$null
操作数0
:
(...)
操作的 LHS-lt
是为了概念清晰而使用的,但这并不是绝对必要的 - 请参阅about_Operator_Precedence。在PowerShell (Core) 7+中,使用空合并运算符??
,它适用于任何类型的操作数:
# PowerShell 7+ only\n($null ?? 0) -lt 0 # -> $false\n
Run Code Online (Sandbox Code Playgroud)\n在不支持此运算符的Windows PowerShell中,请使用虚拟计算:
\n# Windows PowerShell\n(0 + $null) -lt 0 # -> $false\n
Run Code Online (Sandbox Code Playgroud)\n虽然类似的东西[int] $null -lt 0
也可以工作,但它要求您提交特定的数字类型,因此如果操作数碰巧高于[int]::MaxValue
,则表达式将失败;[double] $null -lt 0
可以最大限度地降低这种风险,尽管至少在假设上可能会导致准确性的损失。
虚拟添加( 0 +
) 绕过了这个问题,让 PowerShell 应用其通常的按需类型加宽。
顺便说一句:这种自动类型加宽也可能表现出意想不到的行为,因为全整数计算的结果需要比任一操作数的类型可以容纳的类型更宽的类型[double]
,即使更大的整数类型就足够了,它也总是被加宽到;例如([int]::MaxValue + 1).GetType().Name
return Double
,即使[long]
结果就足够了,导致潜在的准确性损失 - 请参阅此答案以获取更多信息。
归档时间: |
|
查看次数: |
221 次 |
最近记录: |