Powershell - 如何使用$ List.convertAll()或备用C#方法克隆列表

时间:2018-06-01 19:52:36

标签: powershell clone deep-copy convertall

假设我有一个清单:

$DeletedUsers = New-Object System.Collections.Generic.List[System.object]

因此,我可以轻松地从集合中添加和删除用户。

我希望能够将此列表传递给执行某些操作的函数,但不修改原始列表,并且它必须保持相同的通用列表类型。

convertAll()似乎完全符合我的要求,而不必使用foreach-object自行创建新列表,但我不了解如何利用过载定义(或非常明白他们的意思)。

C#中有很多例子,但是我还没能找到一个在PoSH中演示它的例子。

示例场景:

假设$ DeletedUsers包含PSCustomObject类型的User对象列表。使用典型的" User"部门或就业状况等属性。此列表应该能够传递给将更改users属性状态的函数,然后可以将这些函数添加到相同Generic.List类型的单独输出列表中。

目前示例函数的任何更改。

    Function ProcessUser {

    [Cmdletbinding()]
    Param($DeletedUsers)

    begin{$DeletedUsersClone = $($DeletedUsers).psobject.copy()} #OR similar

    process{
    $DeletedUsersClone | foreach { $_ | Add-Member -NotePropertyName 
    "Processed" -NotePropertyValue "Processed:00"; $Outputlist.add($_)} 
           }
                         }

影响原始$ DeletedUsers,错误地将处理过的信息添加到应该保持静态的列表中。

还有其他方法可以防止这种情况影响脚本的最终目标,但问题是:

如何使用内置C#方法创建System.Collections.Generic.List [System.object]的真实,未引用的克隆。

2 个答案:

答案 0 :(得分:2)

诀窍是使用带有显式强制转换的脚本块到委托类型。这看起来像:

$DeletedUsers.ConvertAll([converter[object,object]] {param ($i) <# do convert #> })

答案 1 :(得分:0)

注意:

  • 后来很明显,OP正在寻找原始列表的克隆;即,不仅要将整个清单克隆,还要其元素

  • 此答案仅说明如何创建克隆(以及如何以只读方式传递列表)。

    • 请参阅Bruce Payette's helpful answer了解基于.ConvertAll method深层克隆方法;对于[pscustomobject]个实例,您将使用以下内容(但请注意.psobject.Copy()仅创建[pscustomobject]个实例本身的副本):

      $DeletedUsers.ConvertAll([converter[pscustomobject, pscustomobject]] {param ($obj) $obj.psobject.copy() })
      
  • 如果您想将列表的浅层克隆传递给被叫方:

    • 通过[Collections.Generic.List[object]]::new($DeletedUsers)(PSv5 +语法)
    • 或者,如果列表元素的类型未知或您不想重复,请传递:$DeletedUsers.GetRange(0, $DeletedUsers.Count)
  • 如果您只是希望阻止被叫方意外修改

    • 通过$DeletedUsers.AsReadOnly() - 然而, 更改了类型,即[Collections.ObjectModel.ReadOnlyCollection[object]]