具有无限深度的哈希表。为什么?如何避免?
HashTable with endless depth. Why? How to avoid?
当我使用 $emptyHashTable 变量创建一个空哈希表时,它似乎生成了一个无限深度的哈希表。想不通为什么。
当我使用 @{} 时它工作正常。
代码示例
cls
$L1 = "L1"
$emptyHashTable = @{}
# Correct, hashtable contains 1 sub-hashtable
$proj1 = @{}
$proj1."$L1" = @{}
# Wrong, endless hashtable depth
$proj2 = @{}
$proj2."$L1" = $emptyHashTable
# Wrong, endless hashtable depth
$proj3 = $emptyHashTable
$proj3."$L1" = @{}
# Wrong, endless hashtable depth
$proj4 = $emptyHashTable
$proj4."$L1" = $emptyHashTable
Write-Host
Write-Host "proj1"
Write-Host "Level 0: " $proj1.GetType()
Write-Host "Level 1: " $proj1.L1.GetType()
Write-Host "Level 2: " $proj1.L1.L1.GetType() # Will generate error: You cannot call a method on a null-valued expression.
Write-Host
Write-Host "proj2"
Write-Host "Level 0: " $proj2.GetType()
Write-Host "Level 1: " $proj2.L1.GetType()
Write-Host "Level 2: " $proj2.L1.L1.GetType()
Write-Host "Level 3: " $proj2.L1.L1.L1.GetType()
Write-Host "Level 4: " $proj2.L1.L1.L1.L1.GetType()
Write-Host
Write-Host "proj3"
Write-Host "Level 0: " $proj3.GetType()
Write-Host "Level 1: " $proj3.L1.GetType()
Write-Host "Level 2: " $proj3.L1.L1.GetType()
Write-Host "Level 3: " $proj3.L1.L1.L1.GetType()
Write-Host "Level 4: " $proj3.L1.L1.L1.L1.GetType()
Write-Host
Write-Host "proj4"
Write-Host "Level 0: " $proj4.GetType()
Write-Host "Level 1: " $proj4.L1.GetType()
Write-Host "Level 2: " $proj4.L1.L1.GetType()
Write-Host "Level 3: " $proj4.L1.L1.L1.GetType()
Write-Host "Level 4: " $proj4.L1.L1.L1.L1.GetType()
结果
proj1
Level 0: System.Collections.Hashtable
Level 1: System.Collections.Hashtable
You cannot call a method on a null-valued expression.
At D:\Xandorra\SQL\bmsHashTableTest.ps1:25 char:1
+ Write-Host "Level 2: " $proj1.L1.L1.GetType() # Will generate error: You cannot ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
proj2
Level 0: System.Collections.Hashtable
Level 1: System.Collections.Hashtable
Level 2: System.Collections.Hashtable
Level 3: System.Collections.Hashtable
Level 4: System.Collections.Hashtable
proj3
Level 0: System.Collections.Hashtable
Level 1: System.Collections.Hashtable
Level 2: System.Collections.Hashtable
Level 3: System.Collections.Hashtable
Level 4: System.Collections.Hashtable
proj4
Level 0: System.Collections.Hashtable
Level 1: System.Collections.Hashtable
Level 2: System.Collections.Hashtable
Level 3: System.Collections.Hashtable
我正在使用 Powershell 4.0
我的 $PSVersionTable:
Name Value
---- -----
PSVersion 4.0
WSManStackVersion 3.0
SerializationVersion 1.1.0.1
CLRVersion 4.0.30319.34014
BuildVersion 6.3.9600.17400
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0}
PSRemotingProtocolVersion 2.2
您忽略了一个事实,即对象是按引用传递的,而不是按值传递的。
正是您的测试结构使这些结果蒙上了阴影。 运行 每个人 $projX
在自己的 powershell 实例中分配,没有 运行 其他实例,它应该按预期工作。
例如,当你写:
$proj2."$L1" = $emptyHashTable
$proj3 = $emptyHashTable
$proj3."$L1" = @{}
您已将 $proj2.L1
设置为 对 $emptyHashTable
的引用。因此,您还将 $proj3
设置为 reference 到 $proj2.L1
,从而成为 $emptyHashTable
。这意味着 $proj3.L1 = @{}
与 $proj2.L1.L1 = @{}
相同,依此类推。
这似乎是 Powershell v4 中的错误。
同样的代码在Powershell v5中运行时,不会出现无限深度
当我使用 $emptyHashTable 变量创建一个空哈希表时,它似乎生成了一个无限深度的哈希表。想不通为什么。
当我使用 @{} 时它工作正常。
代码示例
cls
$L1 = "L1"
$emptyHashTable = @{}
# Correct, hashtable contains 1 sub-hashtable
$proj1 = @{}
$proj1."$L1" = @{}
# Wrong, endless hashtable depth
$proj2 = @{}
$proj2."$L1" = $emptyHashTable
# Wrong, endless hashtable depth
$proj3 = $emptyHashTable
$proj3."$L1" = @{}
# Wrong, endless hashtable depth
$proj4 = $emptyHashTable
$proj4."$L1" = $emptyHashTable
Write-Host
Write-Host "proj1"
Write-Host "Level 0: " $proj1.GetType()
Write-Host "Level 1: " $proj1.L1.GetType()
Write-Host "Level 2: " $proj1.L1.L1.GetType() # Will generate error: You cannot call a method on a null-valued expression.
Write-Host
Write-Host "proj2"
Write-Host "Level 0: " $proj2.GetType()
Write-Host "Level 1: " $proj2.L1.GetType()
Write-Host "Level 2: " $proj2.L1.L1.GetType()
Write-Host "Level 3: " $proj2.L1.L1.L1.GetType()
Write-Host "Level 4: " $proj2.L1.L1.L1.L1.GetType()
Write-Host
Write-Host "proj3"
Write-Host "Level 0: " $proj3.GetType()
Write-Host "Level 1: " $proj3.L1.GetType()
Write-Host "Level 2: " $proj3.L1.L1.GetType()
Write-Host "Level 3: " $proj3.L1.L1.L1.GetType()
Write-Host "Level 4: " $proj3.L1.L1.L1.L1.GetType()
Write-Host
Write-Host "proj4"
Write-Host "Level 0: " $proj4.GetType()
Write-Host "Level 1: " $proj4.L1.GetType()
Write-Host "Level 2: " $proj4.L1.L1.GetType()
Write-Host "Level 3: " $proj4.L1.L1.L1.GetType()
Write-Host "Level 4: " $proj4.L1.L1.L1.L1.GetType()
结果
proj1
Level 0: System.Collections.Hashtable
Level 1: System.Collections.Hashtable
You cannot call a method on a null-valued expression.
At D:\Xandorra\SQL\bmsHashTableTest.ps1:25 char:1
+ Write-Host "Level 2: " $proj1.L1.L1.GetType() # Will generate error: You cannot ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
proj2
Level 0: System.Collections.Hashtable
Level 1: System.Collections.Hashtable
Level 2: System.Collections.Hashtable
Level 3: System.Collections.Hashtable
Level 4: System.Collections.Hashtable
proj3
Level 0: System.Collections.Hashtable
Level 1: System.Collections.Hashtable
Level 2: System.Collections.Hashtable
Level 3: System.Collections.Hashtable
Level 4: System.Collections.Hashtable
proj4
Level 0: System.Collections.Hashtable
Level 1: System.Collections.Hashtable
Level 2: System.Collections.Hashtable
Level 3: System.Collections.Hashtable
我正在使用 Powershell 4.0
我的 $PSVersionTable:
Name Value
---- -----
PSVersion 4.0
WSManStackVersion 3.0
SerializationVersion 1.1.0.1
CLRVersion 4.0.30319.34014
BuildVersion 6.3.9600.17400
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0}
PSRemotingProtocolVersion 2.2
您忽略了一个事实,即对象是按引用传递的,而不是按值传递的。
正是您的测试结构使这些结果蒙上了阴影。 运行 每个人 $projX
在自己的 powershell 实例中分配,没有 运行 其他实例,它应该按预期工作。
例如,当你写:
$proj2."$L1" = $emptyHashTable
$proj3 = $emptyHashTable
$proj3."$L1" = @{}
您已将 $proj2.L1
设置为 对 $emptyHashTable
的引用。因此,您还将 $proj3
设置为 reference 到 $proj2.L1
,从而成为 $emptyHashTable
。这意味着 $proj3.L1 = @{}
与 $proj2.L1.L1 = @{}
相同,依此类推。
这似乎是 Powershell v4 中的错误。
同样的代码在Powershell v5中运行时,不会出现无限深度