Powershell

如何轉換為 ArrayList,在 param 塊中預設數據,並返回為 ArrayList?

  • February 27, 2020

由於我需要能夠從數組中添加和刪除項目,因此我需要將其轉換為ArrayList與更常見的選項(、、、[string[]][Array]相反的值$Var=@()。我還需要用數據對其進行預設,但函式的呼叫者需要能夠根據需要更改預設。塊中的預設Param()是必需的,因為另一個實體正在尋找預設數據。我嘗試了幾種變體,但這是最有意義的一種:

Function Test-Me{
   Param
   (
    $Properties = [System.Collection.ArrayList]@(
                  "red",
                  "blue",
                  "green")
   )
   $Properties.GetType()
   $Properties.Add("orange")
}

上面的內容很好,只是一旦有人呼叫Test-Me -Properties "Purple","Yellow","Black"$Properties變數就成為標準Array類型(因此添加和刪除方法不起作用)。

我嘗試了更改我聲明預設值的方式的方法。似乎預填充的行為是將類型轉換為正常數組。我認為這是因為我使用@()的是預設,所以我也嘗試()過。

這也不起作用:

Param
(
[System.Collection.ArrayList]
$Properties = @("red",
                "blue",
                "green")
)

我有一個解決方法可以轉換 Param 塊之外的類型,它看起來像這樣:

Function Test-Me{
   Param
   (
    [String[]]
    $Properties = @("red",
                    "blue",
                    "green")
   )

   if("Orange" -notin $Properties){
       [System.Collections.ArrayList]$Properties = $Properties
       $Properties.Add("orange")
   }
}

我覺得我應該能夠ArrayList在 param 塊中轉換為 an 並用數據預設它,並以相同的 datatype 返回,但我無法弄清楚。如果有人這樣做,或者找到了為什麼它不起作用的文件,請回答。

顯式參數類型轉換

您發布的第二個範例(顯式轉換參數變數)正確的方法:

Function Test-Me {
   Param(
       [System.Collections.ArrayList]
       $Properties = @("red","blue","green")
   )

   Write-Host $Properties.GetType().FullName

   if("Orange" -notin $Properties){
       [void]$Properties.Add("orange")
   }

   $Properties
}

導致:

PS C:\> Test-Me
System.Collections.ArrayList
red
blue
green
orange

PS C:\> Test-Me -Properties "one","two","three"
System.Collections.ArrayList
one
two
three
orange

輸出類型

令我驚訝的一件事是,即使使用該[OutputType]屬性,該函式也會輸出一個正常數組(這實際上可能是一個錯誤預期的行為,請參閱下面的更新):

Function Test-Me {
   [OutputType([System.Collections.ArrayList])]
   Param(
       [System.Collections.ArrayList]
       $Properties = @("red","blue","green")
   )
   
   if("Orange" -notin $Properties){
       [void]$Properties.Add("orange")
   }

   $Properties
}

仍然導致返回一個正常對像數組:

PS C:\> (Test-Me).GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Object[]                                 System.Array

更新(使用簡單的解決方法)

正如對您的Connect 錯誤送出的評論中所展示的那樣,PowerShell 故意列舉任何可列舉輸出的項目,以便為管道提供一致的行為(從評論者 Derp McDerp 在 Connect 上竊取的偽 C#):

if (returned_value is IEnumerable) {
   foreach (r in returned_value) {
       yield r;
   }
} else {
   yield returned_value;
}

然後訣竅是將集合包裝在一個單項數組中,導致 PowerShell 將其作為單個項進行管道傳輸(注意,before $Properties):

Function Test-Me {
   [OutputType([System.Collections.ArrayList])]
   Param(
       [System.Collections.ArrayList]
       $Properties = @("red","blue","green")
   )
   
   if("Orange" -notin $Properties){
       [void]$Properties.Add("orange")
   }

   ,$Properties
}

現在,我們得到了正確類型的輸出:

PS C:\> (Test-Me).GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     ArrayList                                System.Object

引用自:https://serverfault.com/questions/708832