问题

为什么$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

旁注

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

最佳答案

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

我最初的信念是:

  • 可能会发生某些PowerShell隐式类型强制,其中右侧的内容强制转换为与左侧的类型匹配。例如使用"1"+1时,右边的1变为字符串,输出为"11",但是右边的1+"1"变为数字,输出为2
  • 绝对不会发生这种情况,否则$null + @{}会抛出强制转换错误,或者强制转换并执行null + null = null,不会像那样输出空哈希表。
  • 除了数字以外的其他事物,用A + B加法对于数组连接等事物具有一些基本规则,但除此之外,它将落入下面的.Net Framework并将尝试执行诸如A.op_Addition(B)之类的方法调用,并且它将向上左边的东西说当您尝试在右边添加东西时会发生什么。
  • 这确实发生了,但是这里没有发生。考虑到@{} + 0告诉您哈希表只能添加到哈希表中。 (说谎,您可以将其添加为null)。 0 + @{}告诉您哈希表不包含op_Addition方法。因此,带有null的加法似乎应该给出该错误,但不会,因为它不会退回到这种机制。


  • PSv3语言规范(我认为这是可用的最新版本),请在此处下载:https://www.microsoft.com/en-us/download/details.aspx?id=36389,并提及以下内容:



    通常的算术转换为:



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

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



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

    第7章:引言



    从我在规范中可以看到,PowerShell似乎未定义$ null + Hashtable操作,并且+的相应方法是op_Addition-哈希表没有的方法,请参见前面的错误代码-这是不会抛出该错误,不仅是该错误,而且在加0的情况下,错误来自右操作数而不是左操作数。

    规范中另一个有趣的地方是:



    因此,摘要似乎是:
  • @{} + $null-触发PowerShell添加两个哈希表的处理,即使规范未说明会这样做。
  • $null + @{}-似乎有一个隐式的$null + x = x规则,尽管该规范似乎没有提及它,并且可能取决于实现。
  • [<type>]$null-将$ null强制转换为数字类型会导致0(6.15算术转换),但是将其强制转换为其他任何值(?)似乎会导致$ null(在规范中未列出)。
  • 注释和链接链说$null没有类型违反了PowerShell规范4.1.2“空类型”,其中说“空类型具有一个实例,自动变量$ null(§2.3.2.2),也称为空值。未指定此类型的特征。”因此,至少在术语上,即使您无法在PowerType上将它描述为一种类型,..
  • 10-04 14:49
    查看更多