组合哈希表时PowerShell的行为

组合哈希表时PowerShell的行为,powershell,null,hashtable,powershell-5.0,Powershell,Null,Hashtable,Powershell 5.0,问题 为什么$null+@{}有效,而@{}+$null无效;即使null被强制转换为哈希表(@{}+([hashtable]$null)) 示例代码 [hashtable]$a = @{demo1=1;demo2='two'} [hashtable]$b = @{demo3=3;demo4='Ivy'} [hashtable]$c = $null #combining 2 hashtables creates 1 with both hashes properties (would er

问题

为什么
$null+@{}
有效,而
@{}+$null
无效;即使null被强制转换为哈希表(
@{}+([hashtable]$null)

示例代码

[hashtable]$a = @{demo1=1;demo2='two'} 
[hashtable]$b = @{demo3=3;demo4='Ivy'} 
[hashtable]$c = $null

#combining 2 hashtables creates 1 with both hashes properties (would error if any properties were common to both)
write-verbose 'a + b' -Verbose
($a + $b)

#combining a null hashtable with a non-null hashtable works
write-verbose 'c + a' -Verbose
($c + $a)

#combing 2 null hashtables is fine; even if we've not explicitly cast null as a hashtable
write-verbose 'c + null' -Verbose
($c + $null)

#however, combinging a hashtable with null (i.e. same as second test, only putting null as the right argument instead of the left, produces an error
write-verbose 'a + c' -Verbose
($a + $c)
输出

Name                           Value                                                                                                                                                                                                                 
----                           -----                                                                                                                                                                                                                 
demo3                          3                                                                                                                                                                                                                     
demo4                          Ivy                                                                                                                                                                                                                   
demo1                          1                                                                                                                                                                                                                     
demo2                          two                                                                                                                                                                                                                   
VERBOSE: c + a
demo1                          1                                                                                                                                                                                                                     
demo2                          two                                                                                                                                                                                                                   
VERBOSE: c + d
VERBOSE: a + c
A hash table can only be added to another hash table.
At line:19 char:1
+ ($a + $c)
+ ~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : AddHashTableToNonHashTable
旁注

[hashtable]$a = @{demo1=1;demo2='two'} 
[hashtable]$b = @{demo3=3;demo4='Ivy'} 
[hashtable]$c = $null

#combining 2 hashtables creates 1 with both hashes properties (would error if any properties were common to both)
write-verbose 'a + b' -Verbose
($a + $b)

#combining a null hashtable with a non-null hashtable works
write-verbose 'c + a' -Verbose
($c + $a)

#combing 2 null hashtables is fine; even if we've not explicitly cast null as a hashtable
write-verbose 'c + null' -Verbose
($c + $null)

#however, combinging a hashtable with null (i.e. same as second test, only putting null as the right argument instead of the left, produces an error
write-verbose 'a + c' -Verbose
($a + $c)

顺便说一句,这让我发现了哈希表空合并操作的一个有用技巧:
($c+@{})
。e、 g.
($a+($c++{}))
避免了上面产生的错误/
($a++{})+($c++}))
为我们提供了一种完全安全的方法来添加哈希表,其中任何一个值都可能为空。

我试图找出确切的原因,但我不能确定

我最初的信念是:

  • 可能会发生某些PowerShell隐式类型强制,其中右侧的内容被强制转换为与左侧的类型匹配。e、 g.使用
    “1”+1
    时,右侧的1变成字符串,输出为
    “11”
    ,但
    1+“1”
    右侧变成数字,输出为
    2
    • 这肯定不会发生,或者
      $null+@{}
      会抛出强制转换错误,或者强制转换并执行null+null=null,而不会像它那样输出空哈希表
  • 对数字以外的事物添加A+B有一些基本规则,如数组连接,但除此之外,它将落在下面的.Net框架中,并尝试执行方法调用,如
    A.op_Addition(B)
    当您尝试将右侧的内容添加到左侧时,将由左侧的内容决定会发生什么。
    • 这确实发生了,但在这里没有发生。考虑<代码> @ {}+0 告诉您只能将一个哈希表添加到一个哈希表中。(如果是,则可以将其添加到null)。并且
      0+@{}
      告诉您哈希表不包含
      op_Addition
      方法。因此,null的加法似乎应该给出这个错误,但是没有,因为它没有回到这个机制

PSv3语言规范(我认为这是最新的可用版本)在此处下载:,其中提到了附加内容:

7.7.1加法说明:加法运算符+的结果是两个操作数在通常运算后指定的值之和 已应用算术转换(§6.15)

通常的算术转换表示:

如果两个操作数均未指定数值类型的值,则[…]所有指定值$null的操作数将转换为int类型的零,并且该过程将继续进行下面列出的数值转换

这意味着在两个示例中$null都转换为0。虽然这不可能发生,因为
0+@{}
@{}+0
都是错误

第7.7节中明确提到添加两个哈希表:

7.7.4哈希表串联说明:当两个操作数都指定哈希表时,二进制+运算符将创建一个新的哈希表 包含由后面的左操作数指定的元素的 由右操作数指定的元素立即执行

好的,哈希表的添加由PowerShell引擎处理,但只添加两个哈希表

第7节。导言说:

Windows PowerShell:如果PowerShell未定义操作,将检查左操作数指定的值类型,以查看其是否具有相应的op_uu方法

从规范中可以看出,PowerShell似乎没有定义$null+哈希表操作,
+
的对应方法是
op\u Addition
——哈希表没有的方法,请参见前面的错误代码——这并没有引发错误,不仅如此,如果加0,错误来自右操作数,而不是左操作数

规范中另一个有趣的部分是:

4.1.2未指定空类型的特征


因此,总结似乎是:

  • @{}+$null
    -正在触发PowerShell处理添加两个哈希表,即使规范没有说它会这样做
  • $null+@{}
    -看起来有一个隐式的
    $null+x=x
    规则,尽管规范似乎没有提到它,而且它可能依赖于实现
  • []$null
    -将$null强制转换为数字类型将导致0(6.15算术转换),但将其强制转换为任何其他(?)似乎会导致$null(不在规范中)
  • 注释和链接链表示,
    $null
    没有类型,这与PowerShell规范4.1.2“null类型”相抵触,后者表示“null类型有一个实例,即自动变量$null(§2.3.2.2),也称为null值。此类型的特征未指定。”因此,至少在术语上,它在PowerShell中被描述为一个类型,即使您无法在其上获取type()
类型转换$null产生$null:
([hashtable]$null)-eq$null
为真
$null+@{}
有效,因为添加到$null.Ah没有限制;所以null是无类型的,即使是强制转换。多谢各位。有道理/奇怪的是,这不是我以前遇到过的情况。关于C#的相关回答: