我一直在将 $psBoundParameters 添加到这样的哈希表中。
$seedTaskState = @{
arguments = $PSBoundParameters
}
后来,我需要使用这些相同的参数来调用下一个函数,并更改其中一个值。所以我就用了这个
$nestedTaskParameters = $seedTaskState.arguments
然后更改了我需要更改的一个值。这...不起作用,因为复杂类型是通过引用的,所以我更改了原始绑定参数,这会导致各种问题。
我可以将
$nestedTaskParameters
初始化为哈希表,然后循环遍历绑定参数并添加它们,就像这样。
$nestedTaskParameters = @{}
foreach ($key in $seedTaskState.arguments.Keys) {
$nestedTaskParameters.Add($key, $seedTaskState.arguments.$key)
}
我以为这可能有用,而且更优雅
$nestedTaskParameters = $seedTaskState.arguments.Clone()
但是
.Clone()
仅适用于哈希表,不适用于绑定参数字典。
所以我尝试先将
$seedTaskState.arguments
转换为哈希表,然后克隆,就像这样。
$nestedTaskParameters = ([Hashtable]$seedTaskState.arguments).Clone()
这似乎有效,但也远远超出了我的舒适区,所以我想知道这种方法是否存在某种陷阱?
如果您的意图只是使用
arguments
进行论证 splatting,
可以将自动
$PSBoundParameters
变量的条目(其类型源自通用字典(System.Collections.Generic.Dictionary`2
))复制到哈希表([hashtable]
)中。 )通过 cast(在幕后调用适当的构造函数)。
.Clone()
。System.Collections.Generic.IDictionary`2
.NET 接口或其非通用对应物 System.Collections.IDictionary
. 的类字典类型
警告:
生成的哈希表是与$PSBoundParameters
分离的条目集合,即您可以独立地添加或删除条目或为其条目分配新值,而不会影响
$PSBoundParameters
。
但是,如果
$PSBoundParameters
条目值恰好是.NET引用类型的实例,则修改任一字典中的这些值都会影响两个字典,因为两个字典中的相应条目都“指向”(引用)完全相同的对象实例。也就是说, [hashtable]
构造函数创建的是 $PSBoundParameters
中条目的所谓 shallow 副本,这同样适用于在现有哈希表上调用 .Clone()
。
如果您需要避免这种情况,则必须手动创建此类值的深层副本,这可能很重要;要确定给定值是否是 .NET 引用类型的实例,请使用
-not $someValue.GetType().IsValueType
请参阅此答案了解更多信息。
# Sample function.
function Foo {
param(
$bar,
$baz
)
# Effectively copy the entries from $PSBoundParameters into a
# new hashtable.
$hashtable = [hashtable] $PSBoundParameters
# Add new entries to the hashtable.
$hashtable.new1 = 'stuff1'
$hashtable.new2 = 'stuff2'
# Remove one.
$hashtable.Remove('bar')
# Modify the instance of the .NET reference type stored in the entry
# with key 'baz'.
# THIS AFFECTS THE ORIGINAL ENTRY IN $PSBoundParameters TOO.
$hashtable.baz.prop = 2
# Output the two dictionaries.
'-- $PSBoundParameters'
$PSBoundParameters
"`n-- hashtable`n"
$hashtable
}
# Call the function with an instance of a value type and a reference type.
Foo 42 ([pscustomobject] @{ prop = 1 })
上面的结果如下,这表明直接修改其值为 .NET 引用类型实例的条目会影响 both 字典,而添加和删除条目则不会:
-- $PSBoundParameters
Key Value
--- -----
bar 42
baz @{prop=2}
-- hashtable
new2 stuff2
new1 stuff1
baz @{prop=2}
您关于转换为哈希表是克隆的说法是不正确的。我对此进行了测试,如果您不想影响原始表,您仍然需要克隆。
所以这很糟糕: $hashtable = [hashtable] $PSBoundParameters
这有效: $hashtable = ([hashtable] $PSBoundParameters).Clone()