Como converter como ArrayList, pré-configurar dados no bloco de parâmetros e retornar como ArrayList?

2

Como preciso adicionar e remover itens de uma matriz, preciso convertê-los em ArrayList em vez das opções mais comuns ( [string[]] , [Array] , $Var=@() ). Eu também preciso predefini-lo com dados, mas o chamador da função precisa ter a capacidade de alterar a predefinição como desejarem. A predefinição no bloco Param() é necessária, pois outra entidade está procurando dados predefinidos. Eu tentei várias variações, mas aqui está o que faz mais sentido:

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

O acima é ótimo, exceto que assim que alguém chamar Test-Me -Properties "Purple","Yellow","Black" , a variável $Properties se tornará um padrão Array type (pelo qual os métodos add e remove não funcionam).

Eu tentei métodos para alterar a forma como declarei os valores predefinidos. Parece que o ato de preencher previamente está convertendo o tipo em uma matriz regular. Eu percebi que isso era porque eu estava usando @() com as predefinições, então eu tentei () também.

Isso não funciona:

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

Eu tenho um trabalho em torno do qual converte o tipo fora do bloco Param e se parece com isso:

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

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

Eu sinto que deveria ser capaz de converter como ArrayList no bloco de parâmetros e pré-configurar os dados, e retornar como o mesmo tipo de dados , mas não consegui descobrir. Se alguém faz ou encontra documentação porque não funciona, por favor responda.

    
por Colyn1337 27.07.2015 / 18:48

1 resposta

3

Casting explícito de tipo de parâmetro

O segundo exemplo que você postou (explicitamente lançando a variável de parâmetro) é o caminho correto a seguir:

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
}

Como resultado:

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

Uma coisa que me surpreendeu, porém, é que, mesmo com o atributo [OutputType] , a função gera uma matriz regular (isso pode ser um comportamento desejado bug , veja a atualização abaixo):

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

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

    $Properties
}

Ainda resultando em uma matriz de objetos regular sendo retornada:

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

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

Atualizar (com solução fácil)

Conforme demonstrado no comentário sobre o seu Conectar envio de bugs , o PowerShell deliberadamente enumera os itens de qualquer enumerável saída para fornecer um comportamento consistente para o pipeline (pseudo-C # roubado do comentarista Derp McDerp no Connect):

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

O truque é envolver a coleção em uma matriz de item único, fazendo com que o PowerShell canalize-a como um único item (observe para , antes de $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
}

e agora, obtemos uma saída com o tipo correto:

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

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     ArrayList                                System.Object
    
por 28.07.2015 / 17:30