将 $PSBoundParameters 转换为 [HashTable] 以启用 .Clone()

Cast $PSBoundParameters to [HashTable] to enable .Clone()

我一直在像这样将 $psBoundParameters 添加到散列 table。

$seedTaskState = @{
   arguments = $PSBoundParameters
}

稍后,我需要使用相同的参数来调用下一个函数,其中一个值已更改。所以我用了这个

$nestedTaskParameters = $seedTaskState.arguments

然后更改了我需要更改的一个值。哪个...不起作用,因为复杂类型是通过引用所以我正在更改原始绑定参数,这会导致各种问题。

我可以将 $nestedTaskParameters 初始化为散列 table 并遍历绑定参数并添加它们,就像这样。

$nestedTaskParameters = @{}
foreach ($key in $seedTaskState.arguments.Keys) {
    $nestedTaskParameters.Add($key, $seedTaskState.arguments.$key)
}

而且我认为这可能行得通,而且更优雅

$nestedTaskParameters = $seedTaskState.arguments.Clone()

.Clone() 仅适用于散列table,不适用于绑定参数字典。

所以我尝试先将 $seedTaskState.arguments 转换为散列 table,然后像这样克隆。

$nestedTaskParameters = ([Hashtable]$seedTaskState.arguments).Clone()

这似乎可行,但也超出了我的舒适范围,所以我想知道这种方法是否存在某种问题?

Splatting 适用于任何实现 System.Collections.Generic.IDictionary`2 .NET interface or its non-generic counterpart, System.Collections.IDictionary.

的类似字典的类型

警告

  • 生成的哈希表是 $PSBoundParameters 分开的 条目的集合,即您可以添加或删除条目或将新值分配给它的条目独立,不影响 $PSBoundParameters.

  • 但是,如果 $PSBoundParameters 条目值恰好是 .NET reference types 的实例,从任一字典修改这些值都会影响 两者 词典,因为两个词典中的相应条目“指向”(引用)完全相同的对象实例。也就是说,[hashtable] 构造函数创建的是 shallow 中条目的副本 $PSBoundParameters,以及这同样适用于在现有哈希表上调用 .Clone()

    • 如果您需要避免这种情况,则必须手动创建此类值的 deep 副本,这可能很重要;要确定给定值是否是 .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}