about_Enum

Descrição breve

A enum instrução declara uma enumeração. Uma enumeração é um tipo distinto que consiste em um conjunto de rótulos nomeados chamado lista de enumeradores.

Descrição longa

A enum instrução permite que você crie um conjunto de rótulos fortemente tipados. Você pode usar essa enumeração no código sem precisar analisar ou verificar se há erros de ortografia.

As enumerações são representadas internamente como tipos de valor integral com um valor inicial de zero. Por padrão, as enumerações do PowerShell usam System.Int32 ([int]) como o tipo subjacente. Por padrão, o PowerShell atribui ao primeiro rótulo da lista o valor zero. Por padrão, o PowerShell atribui os rótulos restantes com inteiros consecutivos.

Na definição, você pode dar aos rótulos qualquer valor inteiro. Rótulos sem valor atribuído recebem o próximo valor inteiro.

Sintaxe

As enumerações usam as seguintes sintaxes:

Sintaxe de definição de enumeração de número inteiro

[[<attribute>]...] enum <enum-name> {
    <label> [= <int-value>]
    ...
}

Sintaxe de definição de enumeração de tipo subjacente específica

[[<attribute>]...] enum <enum-name> : <underlying-type-name> {
    <label> [= <int-value>]
    ...
}

Sintaxe de definição de enumeração de sinalizador

[[<attribute>]...] [Flag()] enum <enum-name>[ : <underlying-type-name>] {
    <label 0> [= 1]
    <label 1> [= 2]
    <label 2> [= 4]
    <label 3> [= 8]
    ...
    ...
}

Sintaxe de acesso de enumeração

[<enum-name>]::<label>

Exemplos

Exemplo 1 - Enumeração mínima

O bloco de código a seguir define a enumeração MarkdownUnorderedListCharacter com três rótulos. Ele não atribui valores explícitos a nenhum rótulo.

enum MarkdownUnorderedListCharacter {
    Asterisk
    Dash
    Plus
}

O próximo bloco de código mostra como os valores inteiros e de cadeia de caracteres se comportam quando convertidos no tipo de enumeração.

$ValuesToConvert = @(0, 'Asterisk', 1, 'Dash', 2, 'Plus')
foreach ($Value in $ValuesToConvert) {
    [MarkdownUnorderedListCharacter]$EnumValue = $Value

    [pscustomobject]@{
        AssignedValue = $Value
        Enumeration   = $EnumValue
        AreEqual      = $Value -eq $EnumValue
    }
}
AssignedValue Enumeration AreEqual
------------- ----------- --------
            0    Asterisk     True
     Asterisk    Asterisk     True
            1        Dash     True
         Dash        Dash     True
            2        Plus     True
         Plus        Plus     True

A conversão de inteiros iguais ao valor de uma enumeração retorna essa enumeração. A conversão de cadeias de caracteres iguais ao rótulo de uma enumeração retorna essa enumeração.

Exemplo 2 – Valores de enumeração explícitos e sinônimos

O exemplo a seguir mostra uma enumeração de objetos que se correlacionam com arquivos de mídia. A definição atribui valores explícitos aos valores subjacentes de music, picture, video. Os rótulos imediatamente após uma atribuição explícita obtêm o próximo valor inteiro. Você pode criar sinônimos atribuindo o mesmo valor a outro rótulo; Veja os valores construídos para: ogg, oga, mogg, , jpgou mpg, jpegmpeg, , .

enum MediaTypes {
    unknown
    music   = 10
    mp3
    aac
    ogg     = 15
    oga     = 15
    mogg    = 15
    picture = 20
    jpg
    jpeg    = 21
    png
    video   = 40
    mpg
    mpeg    = 41
    avi
    m4v
}

O GetEnumNames() método retorna a lista dos rótulos para a enumeração.

[MediaTypes].GetEnumNames()
unknown
music
mp3
aac
ogg
oga
mogg
picture
jpg
jpeg
png
video
mpg
mpeg
avi
m4v

O GetEnumValues() método retorna a lista dos valores para a enumeração.

[MediaTypes].GetEnumValues()
unknown
music
mp3
aac
ogg
ogg
ogg
picture
jpg
jpg
png
video
mpg
mpg
avi
m4v

Observação

GetEnumNames() e GetEnumValues() parecem retornar os mesmos resultados; uma lista de valores nomeados. No entanto, internamente, GetEnumValues() enumera os valores e, em seguida, mapeia os valores em nomes. Leia a lista com atenção e você notará que ogg, oga, e mogg aparecem na saída de GetEnumNames(), mas a saída de GetEnumValues() mostra oggapenas . A mesma coisa acontece com jpg, jpeg, e mpg, mpeg. O nome que o PowerShell retorna para valores de sinônimos não é determinístico.

Você pode usar o GetEnumName() método para obter um nome associado a um valor específico. Se houver vários nomes associados a um valor, o método retornará o primeiro nome definido.

[MediaTypes].GetEnumName(15)
ogg

O exemplo a seguir mostra como mapear cada nome para seu valor.

[MediaTypes].GetEnumNames() | ForEach-Object {
  [pscustomobject]@{
    Name = $_
    Value = [int]([MediaTypes]::$_)
  }
}
Name    Value
----    -----
unknown     0
music      10
mp3        11
aac        12
ogg        15
oga        15
mogg       15
picture    20
jpg        21
jpeg       21
png        22
video      40
mpg        41
mpeg       41
avi        42
m4v        43

Você pode especificar um único valor de enumeração por seu rótulo com a sintaxe [<enum-name>]::<label>.

[MediaTypes]::png
[MediaTypes]::png -eq 22
png
True

Exemplo 3 - Enumeração como sinalizadores

O bloco de código a seguir cria a enumeração FileAttributes como um conjunto de sinalizadores de bits. O valor de cada rótulo é o dobro do valor do rótulo anterior.

[Flags()] enum FileAttributes {
    Archive    = 1
    Compressed = 2
    Device     = 4
    Directory  = 8
    Encrypted  = 16
    Hidden     = 32
}

[FileAttributes]$file1 =  [FileAttributes]::Archive
[FileAttributes]$file1 += [FileAttributes]::Compressed
[FileAttributes]$file1 += [FileAttributes]::Device
"file1 attributes are: $file1"

[FileAttributes]$file2 = [FileAttributes]28 ## => 16 + 8 + 4
"file2 attributes are: $file2"
file1 attributes are: Archive, Compressed, Device
file2 attributes are: Device, Directory, Encrypted

Para testar se um sinalizador específico está definido, você pode usar o operador -bandde comparação binária . Este exemplo testa os atributos Device e Archive no valor de $file2.

PS > ($file2 -band [FileAttributes]::Device) -eq [FileAttributes]::Device
True

PS > ($file2 -band [FileAttributes]::Archive) -eq [FileAttributes]::Archive
False

Você também pode usar o HasFlag() método para testar se um sinalizador específico está definido. Este exemplo testa os atributos Device e Hidden no valor de $file1.

PS > $file1.HasFlag([FileAttributes]::Device)
True

PS > $file1.HasFlag([FileAttributes]::Hidden)
False

Exemplo 4 - Enumeração como um parâmetro

No exemplo a seguir, a função ConvertTo-LineEndingRegex define o parâmetro InputObject com o tipo EndOfLine.

enum EndOfLine {
    CR   = 1
    LF   = 2
    CRLF = 3
}

function ConvertTo-LineEndingRegex {
    [CmdletBinding()]
    param (
        [Parameter(ValueFromPipeline)]
        [EndOfLine[]]$InputObject
    )

    process {
        switch ($InputObject) {
            CR   {  '\r'  }
            LF   {  '\n'  }
            CRLF { '\r\n' }
        }
    }
}

[EndOfLine]::CR | ConvertTo-LineEndingRegex

'CRLF' | ConvertTo-LineEndingRegex

ConvertTo-LineEndingRegex 2
\r

\r\n

\n

No exemplo, a primeira instrução que chama ConvertTo-LineEndingRegex passa o valor de enumeração para CR. A segunda instrução passa a cadeia de caracteres 'CRLF', que é convertida em um LineEnding. A terceira instrução especifica o valor 2 do parâmetro, que é mapeado para o LF rótulo.

Você pode ver as opções de conclusão de argumento digitando o seguinte texto no prompt do PowerShell:

ConvertTo-LineEndingRegex -InputObject <Tab>

Quando você especifica um nome de rótulo ou valor numérico inválido para o parâmetro, a função gera um erro.

ConvertTo-LineEndingRegex -InputObject 0
ConvertTo-LineEndingRegex: Cannot process argument transformation on
parameter 'InputObject'. Cannot convert value "0" to type "EndOfLine" due
to enumeration values that are not valid. Specify one of the following
enumeration values and try again. The possible enumeration values are
"CR,LF,CRLF".

Exemplo 5 – Enumerações com tipos subjacentes específicos

A partir do PowerShell 6.2, você pode definir enumerações com um tipo subjacente específico. Este exemplo mostra os tipos subjacentes válidos para uma enumeração.

O primeiro bloco de código inicializa duas variáveis como matrizes. $EnumTypes é uma matriz vazia para conter os tipos criados dinamicamente. $IntegralTypes é uma matriz que contém os tipos subjacentes válidos para uma enumeração.

$EnumTypes     = @()
$IntegralTypes = @(
    'byte', 'sbyte', 'short', 'ushort', 'int', 'uint', 'long', 'ulong'
)

O próximo bloco de código define um modelo a ser usado para criar dinamicamente as definições de enumeração. Quando o espaço reservado de {0} formato é substituído por um nome de tipo integral, o modelo cria um scriptblock que:

  1. Define uma enumeração chamada <type>Enum, como byteEnum. A enumeração definida usa o tipo integral especificado como o tipo de valor subjacente.

    A enumeração é definida com o Min valor definido como o valor mínimo para o tipo integral. Ele define o Max valor definido como o valor máximo para o tipo integral.

  2. Retorna o tipo recém-definido.

$DefinitionTemplate = @"
enum {0}Enum : {0} {{
    Min = [{0}]::MinValue
    Max = [{0}]::MaxValue
}}

[{0}Enum]
"@

O próximo bloco de código usa o modelo para criar e invocar um scriptblock no escopo atual. Ele adiciona as definições de tipo retornadas na $EnumTypes matriz.

foreach ($IntegralType in $IntegralTypes) {
    $Definition  = $DefinitionTemplate -f $IntegralType
    $ScriptBlock = [scriptblock]::Create($Definition)
    $EnumTypes  += . $ScriptBlock
}

O último bloco de código faz um loop sobre os tipos de enumeração, usando o GetEnumValuesAsUnderlyingType() método para listar os valores como o tipo subjacente. O loop cria um novo objeto para cada valor, mostrando o tipo de enumeração, o tipo de valor, o rótulo e o valor real.

foreach ($EnumType in $EnumTypes) {
    $EnumType.GetEnumValuesAsUnderlyingType() | ForEach-Object {
        [pscustomobject]@{
            EnumType  = $EnumType.FullName
            ValueType = $_.GetType().FullName
            Label     = $EnumType.GetEnumName($_)
            Value     = $_
        }
    }
}
EnumType   ValueType     Label                Value
--------   ---------     -----                -----
byteEnum   System.Byte   Min                      0
byteEnum   System.Byte   Max                    255
sbyteEnum  System.SByte  Max                    127
sbyteEnum  System.SByte  Min                   -128
shortEnum  System.Int16  Max                  32767
shortEnum  System.Int16  Min                 -32768
ushortEnum System.UInt16 Min                      0
ushortEnum System.UInt16 Max                  65535
intEnum    System.Int32  Max             2147483647
intEnum    System.Int32  Min            -2147483648
uintEnum   System.UInt32 Min                      0
uintEnum   System.UInt32 Max             4294967295
longEnum   System.Int64  Max    9223372036854775807
longEnum   System.Int64  Min   -9223372036854775808
ulongEnum  System.UInt64 Min                      0
ulongEnum  System.UInt64 Max   18446744073709551615

Métodos de enumeração

A lista a seguir inclui métodos úteis disponíveis para enumerações no PowerShell e como usá-los.

Formatar

O Format() método estático retorna a saída da cadeia de caracteres formatada para um determinado tipo de enumeração, valor de enumeração e cadeia de caracteres de formato. A saída é a mesma que chamar o método ToString no valor com a cadeia de caracteres de formato especificada.

Você pode usar o método estático no tipo de classe base System.Enum ou em um tipo de enumeração específico.

[System.Enum]::format([<enum-name>], <value>, <format-string>)
[<enum-name>]::format([<enum-name>], <value>, <format-string>)

As cadeias de caracteres de formato válidas são G ou g, D ou d, X ou x, e F ou .f Para obter mais informações, consulte Cadeias de caracteres de formato de enumeração.

O exemplo a seguir usa cada uma das cadeias de caracteres de formato de enumeração com suporte para converter cada valor da enumeração TaskState em suas representações de cadeia de caracteres.

enum TaskState {
    ToDo
    Doing
    Done
}

# String format template for the statements
$Statement = "[System.Enum]::Format([TaskState], {0}, '{1}')"

foreach ($Format in @('G', 'D', 'X', 'F')) {
    $StatementToDo  = $Statement -f 0, $Format
    $StatementDoing = $Statement -f "([TaskState]'Doing')", $Format
    $StatementDone  = $Statement -f '[TaskState]::Done', $Format
    $FormattedToDo  = [System.Enum]::Format(
      [TaskState], 0, $Format
    )
    $FormattedDoing = [System.Enum]::Format(
        [TaskState], ([TaskState]'Doing'), $Format
    )
    $FormattedDone  = [System.Enum]::Format(
      [TaskState], [TaskState]::Done, $Format
    )

    "{0,-62} => {1}" -f $StatementToDo,  $FormattedToDo
    "{0,-62} => {1}" -f $StatementDoing, $FormattedDoing
    "{0,-62} => {1}" -f $StatementDone,  $FormattedDone
}
[System.Enum]::Format([TaskState], 0, 'G')                     => ToDo
[System.Enum]::Format([TaskState], ([TaskState]'Doing'), 'G')  => Doing
[System.Enum]::Format([TaskState], [TaskState]::Done, 'G')     => Done
[System.Enum]::Format([TaskState], 0, 'D')                     => 0
[System.Enum]::Format([TaskState], ([TaskState]'Doing'), 'D')  => 1
[System.Enum]::Format([TaskState], [TaskState]::Done, 'D')     => 2
[System.Enum]::Format([TaskState], 0, 'X')                     => 00000000
[System.Enum]::Format([TaskState], ([TaskState]'Doing'), 'X')  => 00000001
[System.Enum]::Format([TaskState], [TaskState]::Done, 'X')     => 00000002
[System.Enum]::Format([TaskState], 0, 'F')                     => ToDo
[System.Enum]::Format([TaskState], ([TaskState]'Doing'), 'F')  => Doing
[System.Enum]::Format([TaskState], [TaskState]::Done, 'F')     => Done

GetEnumName

O GetEnumName() método de reflexão retorna o nome de um valor de enumeração específico. O valor de entrada deve ser um tipo subjacente válido para uma enumeração, como um inteiro ou um valor de enumeração. Se houver vários nomes associados a um valor, o método retornará o primeiro nome definido.

[<enum-name>].GetEnumName(<value>)
enum GateState {
    Unknown
    Open
    Opening
    Closing
    Closed
}

foreach ($Value in 0..4) {
    [pscustomobject]@{
      IntegerValue = $Value
      EnumName     = [GateState].GetEnumName($Value)
    }
}
IntegerValue EnumName
------------ --------
           0 Unknown
           1 Open
           2 Opening
           3 Closing
           4 Closed

GetEnumNames

O GetEnumNames() método de reflexão retorna os nomes de cada valor de enumeração como cadeias de caracteres. A saída inclui sinônimos.

[<enum-name>].GetEnumNames()
enum Season {
    Unknown
    Spring
    Summer
    Autumn
    Winter
    Fall   = 3
}

[Season].GetEnumNames()
Unknown
Spring
Summer
Fall
Autumn
Winter

GetEnumUnderlyingType

O GetEnumUnderlyingType() método de reflexão retorna o tipo subjacente para os valores de enumeração.

[<enum-name>].GetEnumUnderlyingType()
enum IntBasedEnum {
    Zero
    One
    Two
}
enum ShortBasedEnum : short {
    Zero
    One
    Two
}

foreach ($EnumType in @([IntBasedEnum], [ShortBasedEnum])) {
    [pscustomobject]@{
        EnumType = $EnumType
        ValueType = $EnumType.GetEnumUnderlyingType()
    }
}
EnumType       ValueType
--------       ---------
IntBasedEnum   System.Int32
ShortBasedEnum System.Int16

GetEnumValues

O GetEnumValues() método de reflexão retorna todos os valores definidos para a enumeração.

[<enum-name>].GetEnumValues()
enum Season {
    Unknown
    Spring
    Summer
    Autumn
    Winter
    Fall   = 3
}

[Season].GetEnumValues()
Unknown
Spring
Summer
Fall
Fall
Winter

GetEnumValuesAsUnderlyingType

O GetEnumValuesAsUnderlyingType() método de reflexão retorna todos os valores definidos para a enumeração como o tipo subjacente.

[<enum-name>].GetEnumValuesAsUnderlyingType()
enum IntBasedEnum {
    Zero
    One
    Two
}
enum ShortBasedEnum : short {
    Zero
    One
    Two
}

foreach ($EnumType in @([IntBasedEnum], [ShortBasedEnum])) {
    [pscustomobject]@{
        EnumType = $EnumType
        ValueType = $EnumType.GetEnumValuesAsUnderlyingType()[0].GetType()
    }
}
EnumType       ValueType
--------       ---------
IntBasedEnum   System.Int32
ShortBasedEnum System.Int16

HasFlag

O HasFlag método de instância determina se um sinalizador de bit está definido para um valor de enumeração de sinalizador. Usar esse método é mais curto e fácil de ler do que fazer uma comparação binária e verificação de equivalência.

<enum-value>.HasFlag(<enum-flag-value>)

O exemplo a seguir define a enumeração de sinalizadores ModuleFeatures e mostra quais sinalizadores o valor 39 tem.

[Flags()] enum ModuleFeatures {
    Commands  = 1
    Classes   = 2
    Enums     = 4
    Types     = 8
    Formats   = 16
    Variables = 32
}

$Features = [ModuleFeatures]39

foreach ($Feature in [ModuleFeatures].GetEnumValues()) {
    "Has flag {0,-12}: {1}" -f "'$Feature'", ($Features.HasFlag($Feature))
}
Has flag 'Commands'  : True
Has flag 'Classes'   : True
Has flag 'Enums'     : True
Has flag 'Types'     : False
Has flag 'Formats'   : False
Has flag 'Variables' : True

ÉDefinido

O IsDefined() método estático retorna $true se o valor de entrada for definido para a enumeração e, caso contrário, $false. Use esse método para verificar se um valor é válido para uma enumeração sem precisar lidar com erros de argumento inválidos.

Você pode usar o método estático no tipo de classe base System.Enum ou em um tipo de enumeração específico.

[System.Enum]::IsDefined([<enum-name>], <value>)
[<enum-name>]::IsDefined([<enum-name>], <value>)
enum Season {
    Unknown
    Spring
    Summer
    Autumn
    Winter
    Fall   = 3
}

foreach ($Value in 0..5) {
    $IsValid   = [Season]::IsDefined([Season], $Value)
    $EnumValue = if ($IsValid) { [Season]$Value }

    [pscustomobject] @{
        InputValue = $Value
        IsValid    = $IsValid
        EnumValue  = $EnumValue
    }
}
InputValue IsValid EnumValue
---------- ------- ---------
         0    True   Unknown
         1    True    Spring
         2    True    Summer
         3    True      Fall
         4    True    Winter
         5   False

ToString

O ToString() método de instância retorna o rótulo para um valor de enumeração. Esse método também é a exibição padrão de como um valor de enumeração é exibido como saída. Opcionalmente, você pode especificar uma cadeia de caracteres de formato para controlar como o valor é exibido. Para obter mais informações sobre formatação, consulte Formatando valores de enumeração.

Observação

Para enumerações que definem sinônimos para um valor específico, não escreva código que dependa da saída de ToString(). O método pode retornar qualquer nome válido para o valor.

<enum-value>.ToString([<format-string>])

O exemplo a seguir define a enumeração Shade with Gray como sinônimo de Grey . Em seguida, ele gera objetos que mostram o valor real da enumeração, a enumeração como uma cadeia de caracteres e a enumeração como um inteiro.

enum Shade {
    White
    Grey
    Gray = 1
    Black
}

[Shade].GetEnumValues() | Foreach-Object -Process {
    [pscustomobject]@{
        EnumValue    = $_
        StringValue  = $_.ToString()
        IntegerValue = [int]$_
    }
}
numValue StringValue IntegerValue
--------- ----------- ------------
    White White                  0
     Grey Grey                   1
     Grey Grey                   1
    Black Black                  2

Sinônimos de valor de enumeração

Você pode definir enumerações que dão nomes diferentes ao mesmo valor inteiro. Quando você faz isso, os nomes que apontam para o mesmo valor subjacente são chamados de sinônimos. Enumerações com sinônimos permitem que os usuários especifiquem nomes diferentes para o mesmo valor.

Ao definir uma enumeração com sinônimos, não escreva código que dependa da conversão de um valor de sinônimo em um nome específico. Você pode escrever de forma confiável um código que converte uma cadeia de caracteres sinônima no valor de enumeração. Ao trabalhar com o próprio valor de enumeração, sempre compare-o como um valor de enumeração ou seu tipo subjacente em vez de como uma cadeia de caracteres.

O bloco de código a seguir define a enumeração Shade com Grey e Gray como sinônimos.

enum Shade {
    White
    Grey
    Gray = 1
    Black
}

[Shade]'Grey' -eq [Shade]::Gray
[Shade]::Grey -eq 1
[Shade]'Gray' -eq 1
True
True
True

Enumerações como sinalizadores

Um uso comum de uma enumeração é representar um conjunto de valores mutuamente exclusivos. Por exemplo, uma instância de ArrivalStatus pode ter um valor de Early, OnTime ou Late. Não faz sentido que o valor de uma instância ArrivalStatus reflita mais de uma constante de enumeração.

Em outros casos, no entanto, o valor de um objeto de enumeração pode incluir vários membros de enumeração e cada membro representa um campo de bits no valor de enumeração. Você pode usar o FlagsAttribute para indicar que a enumeração consiste em campos de bits como sinalizadores que os usuários podem combinar.

Para que as enumerações como sinalizadores funcionem corretamente, você deve definir o valor inteiro de cada rótulo como uma potência de dois. Se você não especificar um valor para um rótulo, o PowerShell definirá o valor como um maior que o rótulo anterior.

Você pode definir valores para combinações de sinalizadores comumente usadas para tornar mais fácil para os usuários especificar um conjunto de sinalizadores de uma só vez. O nome do valor deve ser os nomes combinados dos sinalizadores. O valor inteiro deve ser a soma dos valores do sinalizador.

Para determinar se um sinalizador específico está definido para um valor, use o HasFlag() método no valor ou use o operador -bandde comparação binária .

Para obter um exemplo que mostra como usar enumerações de sinalizador e verificar se um sinalizador está definido, consulte o Exemplo 3.

Enumerações como parâmetros

Você pode definir parâmetros de cmdlet que usam uma enumeração como tipo. Quando você especifica uma enumeração como o tipo de um parâmetro, os usuários obtêm o preenchimento automático e a validação do valor do parâmetro. A conclusão do argumento sugere a lista de rótulos válidos para a enumeração.

Quando um parâmetro tem uma enumeração como seu tipo, você pode especificar qualquer um dos seguintes:

  • Uma enumeração, como [<EnumType>]::<Label>
  • O rótulo de uma enumeração como uma cadeia de caracteres
  • O valor numérico de uma enumeração

Para obter um exemplo que mostra o comportamento de um parâmetro de tipo de enumeração, consulte o Exemplo 4.

Enumerações com tipos subjacentes específicos

A partir do PowerShell 6.2, você pode definir enumerações com um tipo subjacente específico. Quando você define uma enumeração sem um tipo subjacente específico, o PowerShell cria a enumeração com [int] (System.Int32) como o tipo subjacente.

O tipo subjacente de uma enumeração deve ser um tipo numérico integral. A lista a seguir inclui os tipos válidos com seu nome curto e nome de tipo completo:

  • byte - System.Byte
  • sbyte - System.SByte
  • short - System.Int16
  • ushort - System.UInt16
  • int - System.Int32
  • uint - System.UInt32
  • long - System.Int64
  • ulong - System.UInt64

Você pode definir um tipo subjacente específico para enumeração como o nome curto ou o nome completo do tipo. As definições a seguir são funcionalmente idênticas. Somente o nome usado para o tipo subjacente é diferente.

enum LongValueEnum : long {
    Zero
    One
    Two
}
enum LongValueEnum : System.Int64 {
    Zero
    One
    Two
}

Formatando valores de enumeração

Você pode converter valores de enumeração em suas representações de cadeia de caracteres chamando o método estático Format, bem como as sobrecargas do método ToString da instância. Você pode usar uma cadeia de caracteres de formato para controlar a maneira precisa na qual um valor de enumeração é representado como uma cadeia de caracteres. Para obter mais informações, consulte Cadeias de caracteres de formato de enumeração.

O exemplo a seguir usa cada uma das cadeias de caracteres de formato de enumeração com suporte (G ou g, D ou d, X ou x, e F ou ) f para converter cada membro da enumeração TaskState em suas representações de cadeia de caracteres.

enum TaskState {
    ToDo
    Doing
    Done
}

[TaskState].GetEnumValues() | ForEach-Object {
    [pscustomobject]@{
        "ToString('G')" = $_.ToString('G')
        "ToString('D')" = $_.ToString('D')
        "ToString('X')" = $_.ToString('X')
        "ToString('F')" = $_.ToString('F')
    }
}
ToString('G') ToString('D') ToString('X') ToString('F')
------------- ------------- ------------- -------------
ToDo          0             00000000      ToDo
Doing         1             00000001      Doing
Done          2             00000002      Done

O exemplo a seguir usa as cadeias de caracteres de formato para valores de uma enumeração de sinalizador.

[Flags()] enum FlagEnum {
    A = 1
    B = 2
    C = 4
}

$FlagValues = @(
    [FlagEnum]::A                                 # 1
    [FlagEnum]::B                                 # 2
    [FlagEnum]::A + [FlagEnum]::B                 # 3
    [FlagEnum]::C                                 # 4
    [FlagEnum]::C + [FlagEnum]::A                 # 5
    [FlagEnum]::C + [FlagEnum]::B                 # 6
    [FlagEnum]::C + [FlagEnum]::A + [FlagEnum]::B # 7
    [FlagEnum]::C + [FlagEnum]::C                 # 8
)

foreach ($Value in $FlagValues) {
    [pscustomobject]@{
        "ToString('G')" = $Value.ToString('G')
        "ToString('D')" = $Value.ToString('D')
        "ToString('X')" = $Value.ToString('X')
        "ToString('F')" = $Value.ToString('F')
    }
}
ToString('G') ToString('D') ToString('X') ToString('F')
------------- ------------- ------------- -------------
A             1             00000001      A
B             2             00000002      B
A, B          3             00000003      A, B
C             4             00000004      C
A, C          5             00000005      A, C
B, C          6             00000006      B, C
A, B, C       7             00000007      A, B, C
8             8             00000008      8

Observe que, para enumerações de sinalizadores, as G cadeias de caracteres de formato e F exibem a lista de sinalizadores de conjunto para o valor delimitado por vírgulas. O último valor, 8, não lista nenhum sinalizador porque não é realmente um conjunto de sinalizadores válido. Você não pode combinar os sinalizadores de enumeração para obter uma soma sem 8 duplicar pelo menos um sinalizador.

Definindo métodos de extensão com Update-TypeData

Você não pode definir métodos na declaração para uma enumeração. Para estender a funcionalidade de uma enumeração, você pode usar o cmdlet Update-TypeData para definir ScriptMethod membros para a enumeração.

O exemplo a seguir usa o Update-TypeData cmdlet para adicionar um GetFlags() método à enumeração de sinalizador FileAttributes . Ele retorna uma matriz dos sinalizadores definidos para o valor.

[Flags()] enum FileAttributes {
    Archive    = 1
    Compressed = 2
    Device     = 4
    Directory  = 8
    Encrypted  = 16
    Hidden     = 32
}

$MemberDefinition = @{
    TypeName   = 'FileAttributes'
    MemberName = 'GetFlags'
    MemberType = 'ScriptMethod'
    Value      = {
        foreach ($Flag in $this.GetType().GetEnumValues()) {
          if ($this.HasFlag($Flag)) { $Flag }
        }
    }
}

Update-TypeData @MemberDefinition

$File = [FileAttributes]28

$File.GetFlags()
Device
Directory
Encrypted

Exportando enumerações com aceleradores de tipo

Por padrão, os módulos do PowerShell não exportam automaticamente classes e enumerações definidas no PowerShell. Os tipos personalizados não estão disponíveis fora do módulo sem chamar uma using module instrução.

No entanto, se um módulo adicionar aceleradores de tipo, esses aceleradores de tipo estarão imediatamente disponíveis na sessão depois que os usuários importarem o módulo.

Observação

A adição de aceleradores de tipo à sessão usa uma API interna (não pública). O uso dessa API pode causar conflitos. O padrão descrito abaixo gerará um erro se um acelerador de tipo com o mesmo nome já existir quando você importar o módulo. Ele também remove os aceleradores de tipo quando você remove o módulo da sessão.

Esse padrão garante que os tipos estejam disponíveis em uma sessão. Ele não afeta o IntelliSense ou a conclusão ao criar um arquivo de script no VS Code. Para obter sugestões de IntelliSense e conclusão para tipos personalizados no VS Code, você precisa adicionar uma using module instrução à parte superior do script.

O padrão a seguir mostra como você pode registrar classes e enumerações do PowerShell como aceleradores de tipo em um módulo. Adicione o snippet ao módulo de script raiz após qualquer definição de tipo. Certifique-se de que a $ExportableTypes variável contenha cada um dos tipos que você deseja disponibilizar aos usuários quando eles importarem o módulo. O outro código não requer nenhuma edição.

# Define the types to export with type accelerators.
$ExportableTypes =@(
    [DefinedTypeName]
)
# Get the internal TypeAccelerators class to use its static methods.
$TypeAcceleratorsClass = [psobject].Assembly.GetType(
    'System.Management.Automation.TypeAccelerators'
)
# Ensure none of the types would clobber an existing type accelerator.
# If a type accelerator with the same name exists, throw an exception.
$ExistingTypeAccelerators = $TypeAcceleratorsClass::Get
foreach ($Type in $ExportableTypes) {
    if ($Type.FullName -in $ExistingTypeAccelerators.Keys) {
        $Message = @(
            "Unable to register type accelerator '$($Type.FullName)'"
            'Accelerator already exists.'
        ) -join ' - '

        throw [System.Management.Automation.ErrorRecord]::new(
            [System.InvalidOperationException]::new($Message),
            'TypeAcceleratorAlreadyExists',
            [System.Management.Automation.ErrorCategory]::InvalidOperation,
            $Type.FullName
        )
    }
}
# Add type accelerators for every exportable type.
foreach ($Type in $ExportableTypes) {
    $TypeAcceleratorsClass::Add($Type.FullName, $Type)
}
# Remove type accelerators when the module is removed.
$MyInvocation.MyCommand.ScriptBlock.Module.OnRemove = {
    foreach($Type in $ExportableTypes) {
        $TypeAcceleratorsClass::Remove($Type.FullName)
    }
}.GetNewClosure()

Quando os usuários importam o módulo, todos os tipos adicionados aos aceleradores de tipo para a sessão ficam imediatamente disponíveis para IntelliSense e conclusão. Quando o módulo é removido, os aceleradores de tipo também são.

Importando enumerações manualmente de um módulo do PowerShell

Import-Module e a #requires instrução importa apenas as funções, aliases e variáveis do módulo, conforme definido pelo módulo. As enumerações não são importadas.

Se um módulo definir classes e enumerações, mas não adicionar aceleradores de tipo para esses tipos, use uma using module instrução para importá-los.

A using module instrução importa classes e enumerações do módulo raiz (ModuleToProcess) de um módulo de script ou módulo binário. Ele não importa consistentemente classes definidas em módulos aninhados ou classes definidas em scripts que são originados por pontos no módulo raiz. Defina as classes que você deseja que estejam disponíveis para usuários fora do módulo diretamente no módulo raiz.

Para obter mais informações sobre a instrução, consulte about_Usingusing.

Carregando código recém-alterado durante o desenvolvimento

Durante o desenvolvimento de um módulo de script, é comum fazer alterações no código e carregar a nova versão do módulo usando Import-Module o parâmetro Force . Isso funciona apenas para alterações em funções no módulo raiz. Import-Module não recarrega nenhum módulo aninhado. Além disso, não há como carregar nenhuma classe atualizada.

Para garantir que você esteja executando a versão mais recente, você deve iniciar uma nova sessão. Classes e enumerações definidas no PowerShell e importadas com uma using instrução não podem ser descarregadas.

Outra prática comum de desenvolvimento é separar seu código em arquivos diferentes. Se você tiver uma função em um arquivo que usa enumerações definidas em outro módulo, deverá usar a using module instrução para garantir que as funções tenham as definições de enumeração necessárias.

Limitações

  • Você não pode decorar valores de enumeração definidos no PowerShell com atributos. Você só pode decorar a declaração de enumeração em si, como acontece com o FlagsAttribute para definir uma enumeração como um conjunto de sinalizadores de bits.

    Solução alternativa: Não há

  • Você não pode definir métodos dentro de definições de enumeração e o PowerShell não dá suporte à definição de [métodos de extensão] como C#.

    Solução alternativa: use o cmdlet Update-TypeData para definir ScriptMethod membros para a enumeração.