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

问题描述 投票:0回答:2

我一直在将 $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()

这似乎有效,但也远远超出了我的舒适区,所以我想知道这种方法是否存在某种陷阱?

powershell casting clone
2个回答
2
投票

Splatting 适用于任何实现

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}

0
投票

您关于转换为哈希表是克隆的说法是不正确的。我对此进行了测试,如果您不想影响原始表,您仍然需要克隆。

所以这很糟糕: $hashtable = [hashtable] $PSBoundParameters

这有效: $hashtable = ([hashtable] $PSBoundParameters).Clone()

© www.soinside.com 2019 - 2024. All rights reserved.