数组访问的奇怪上限
Weird ceilling for array access
我在使用数组索引器时在 PowerShell 中遇到了奇怪的代码片段。为什么您认为它会以下列方式运行?
我期望的标准行为是每次都获取数组的确切成员,在本例中首先是从零开始
(0, 1)[0] == 0 # as expected
(0, 1 -ne 2)[0] == 0 # as expected regardless second member would be casted from bool to int
(0, 1 -ne 0)[0] == 1 # magic starts here
到目前为止,我希望它是将 1 -ne 0
从 bool 转换为 int 的结果,并与数组第一位的 0 一起形成已知的异常,但是:
(0, 60 -ne 0)[0] == 60 # ignores first member and whole (-ne 0) part
(0, 60 -ne 1)[0] == 0 # as expected
(1, 60 -ne 0)[0] == 1 # as expected
在这一点上,它似乎只有在第一个成员是 0
时才会生效,而不管它作为变量传递,第二部分必须正好是 1 -ne 0
# doesn't matter if first member is variable
$x = 0
($x, 1 -ne 0)[0] == 1 # same magic as before
($x, 0 -ne 1)[0] == 0 # as expected by may be caused by leading zero of 0 -ne 1
($x, 0 -ne 0)[0] == null # this is also very weird
($x, 1 -ne 1)[0] == 0 # maybe return of bool comparison or simply first member, I would expect null as before
我知道,只要防止代码在数组中混合 bool 和 int,就可以解决所有关于这些事情的疑惑。
我如何发现它在我们的遗留代码中用作天花板
return ([int]$lastResultCode, 1 -ne 0)
而不是:
if ($lastResultCode == 0) return 1
else return $lastResultCode
但请考虑此代码已经发布的情况,无法更改此代码,而且该机器上可能是 PowerShell 版本的升级,因此可能会更改未来的行为。对于这种情况,我想请您就导致这种行为的原因提出意见。
这里发生了两件事:
,
运算符的优先级高于比较运算符。所以,像这样的表达式:
(0, 1 -ne 0)[0]
实际解析为:
((0, 1) -ne 0)[0]
下阅读有关 PowerShell 运算符优先级的更多信息
PowerShell 比较运算符可用于标量(单个项目)和数组。当您将它们与数组一起使用时,它们将 return 所有满足条件的项目:
PS > (4, 5, 3, 1, 2) -gt 2 # All items greater than 2
4
5
3
PS > (4, 5, 3, 1, 2) -ne 3 # All items that do not equal 3
4
5
1
2
PS >
考虑到这些要点,您所看到的行为就很容易解释了。表达式:
(0, 1 -ne 0)[0]
首先解析为:
((0, 1) -ne 0)[0]
然后变成:
(1)[0]
因为 -ne
return 来自 (0, 1)
的项目不等于 0
,也就是 1
.
解决方法就是多加一组括号:
(0, (1 -ne 0))[0]
这将导致 PowerShell 首先评估 1 -ne 0
部分并按您预期的方式运行:
PS > (0, (1 -ne 0))
0
True
PS > (0, (1 -ne 0))[0]
0
PS >
我在使用数组索引器时在 PowerShell 中遇到了奇怪的代码片段。为什么您认为它会以下列方式运行?
我期望的标准行为是每次都获取数组的确切成员,在本例中首先是从零开始
(0, 1)[0] == 0 # as expected
(0, 1 -ne 2)[0] == 0 # as expected regardless second member would be casted from bool to int
(0, 1 -ne 0)[0] == 1 # magic starts here
到目前为止,我希望它是将 1 -ne 0
从 bool 转换为 int 的结果,并与数组第一位的 0 一起形成已知的异常,但是:
(0, 60 -ne 0)[0] == 60 # ignores first member and whole (-ne 0) part
(0, 60 -ne 1)[0] == 0 # as expected
(1, 60 -ne 0)[0] == 1 # as expected
在这一点上,它似乎只有在第一个成员是 0
时才会生效,而不管它作为变量传递,第二部分必须正好是 1 -ne 0
# doesn't matter if first member is variable
$x = 0
($x, 1 -ne 0)[0] == 1 # same magic as before
($x, 0 -ne 1)[0] == 0 # as expected by may be caused by leading zero of 0 -ne 1
($x, 0 -ne 0)[0] == null # this is also very weird
($x, 1 -ne 1)[0] == 0 # maybe return of bool comparison or simply first member, I would expect null as before
我知道,只要防止代码在数组中混合 bool 和 int,就可以解决所有关于这些事情的疑惑。 我如何发现它在我们的遗留代码中用作天花板
return ([int]$lastResultCode, 1 -ne 0)
而不是:
if ($lastResultCode == 0) return 1
else return $lastResultCode
但请考虑此代码已经发布的情况,无法更改此代码,而且该机器上可能是 PowerShell 版本的升级,因此可能会更改未来的行为。对于这种情况,我想请您就导致这种行为的原因提出意见。
这里发生了两件事:
,
运算符的优先级高于比较运算符。所以,像这样的表达式:(0, 1 -ne 0)[0]
实际解析为:
((0, 1) -ne 0)[0]
下阅读有关 PowerShell 运算符优先级的更多信息
PowerShell 比较运算符可用于标量(单个项目)和数组。当您将它们与数组一起使用时,它们将 return 所有满足条件的项目:
PS > (4, 5, 3, 1, 2) -gt 2 # All items greater than 2 4 5 3 PS > (4, 5, 3, 1, 2) -ne 3 # All items that do not equal 3 4 5 1 2 PS >
考虑到这些要点,您所看到的行为就很容易解释了。表达式:
(0, 1 -ne 0)[0]
首先解析为:
((0, 1) -ne 0)[0]
然后变成:
(1)[0]
因为 -ne
return 来自 (0, 1)
的项目不等于 0
,也就是 1
.
解决方法就是多加一组括号:
(0, (1 -ne 0))[0]
这将导致 PowerShell 首先评估 1 -ne 0
部分并按您预期的方式运行:
PS > (0, (1 -ne 0))
0
True
PS > (0, (1 -ne 0))[0]
0
PS >