Powershell 按值传递复杂对象,而不是按引用

时间:2021-02-19 08:07:16

标签: powershell parameter-passing pass-by-value

我正在尝试处理一个有序字典中的一些数据,然后将其添加到另一个有序字典中,我可以通过重新初始化我的临时字典来做到这一点,就像这样...

$collection = [Collections.Specialized.OrderedDictionary]::new()

foreach ($id in 1..5) {
    $tempCollection = [Collections.Specialized.OrderedDictionary]::new()
    foreach ($char in [Char]'a'..[Char]'e') {
        $letter = ([Char]$char).ToString()
        if ($id % 2 -eq 0) {
            $letter = $letter.ToUpper()
        }
        $int = [Int][Char]$letter
        $tempCollection.Add($letter, $int)
    }
    $collection.Add($id, $tempCollection)
}

foreach ($id in $collection.Keys) {
    Write-Host "$id"
    foreach ($key in $collection.$id.Keys) {
        Write-Host "   $key : $($collection.$id.$key)"
    }
}

但是,我觉得重新初始化有点低效/不优雅,我宁愿只 .Clear() 那个临时变量。这导致了这个......

$collection = [Collections.Specialized.OrderedDictionary]::new()
$tempCollection = [Collections.Specialized.OrderedDictionary]::new()

foreach ($id in 1..5) {
    foreach ($char in [Char]'a'..[Char]'e') {
        $letter = ([Char]$char).ToString()
        if ($id % 2 -eq 0) {
            $letter = $letter.ToUpper()
        }
        $int = [Int][Char]$letter
        $tempCollection.Add($letter, $int)
    }
    $collection.Add($id, $tempCollection)
    $tempCollection.Clear()
}

foreach ($id in $collection.Keys) {
    Write-Host "$id"
    foreach ($key in $collection.$id.Keys) {
        Write-Host "   $key : $($collection.$id.$key)"
    }
}

问题在于,虽然像 string、int、char 等简单对象是按值传递的,但所有复杂对象(例如字典)都是按引用传递的。所以我在 $collection.Add($id, $tempCollection) 的每次迭代中都传递了 SAME 字典,并且 $tempCollection 的最终状态被清除,所以结果是 $collection 的 5 个空成员。

我知道我可以使用 [Ref] 将通常按值传递的内容强制为按引用传递,如 here 所述。而 [Ref] 只是 System.Management.Automation.PSReference 的加速器。所以我需要的是一种按值强制参数的方法,但是 [Val][ByVal] 都不起作用,并且搜索 System.Management.Automation.PSValue 似乎也没有返回任何有用的东西。上面链接的 PSReference doco 说

<块引用>

这个类用于描述这两种引用:

一个。对值的引用:_value 将保存被引用的值。

B.对变量的引用:_value 将持有一个 PSVariable 要引用的变量的实例。

这让我觉得我可以以某种方式达到价值,但对于我的生活,我无法理解如何。我是在正确的轨道上,只是遗漏了一些东西,还是我完全误解了这个文档?

克隆似乎也是一个潜在的解决方案,即 $collection.Add($id, $tempCollection.Clone()),但有序字典没有实现 ICloneable。 .CopyTo() 也不是一个选项,因为它不一定保持元素的顺序。 .AsReadOnly() 也没有,因为

<块引用>

AsReadOnly 方法创建一个围绕当前的只读包装器 OrderedDictionary 集合。对 OrderedDictionary 所做的更改 集合都反映在只读副本中。 OrderedDictionary 也没有像 PSObject 那样实现 .copy()

我也尝试过创建一个新变量,就像这样...

$newCollection = $tempCollection
$collection.Add($id, $newCollection)
$tempCollection.Clear()

这也行不通。因此,通过引用的复杂对象似乎不仅仅适用于传递的参数。

似乎我的有序字典选择/需要几乎是问题的根源,但似乎需要一个未连接的有序字典副本不会是不支持的极端情况。

0 个答案:

没有答案