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 fortemente tipado de rótulos. 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. Os 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 inteira

[[<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>]
    ...
}

Sinalizar sintaxe de definição de enumeração

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

Sintaxe de acesso à 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 inteiro e de cadeia de caracteres se comportam quando convertidos para o 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 que são 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 a 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, ou jpg, jpeg, ou , mpeg.mpg

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, ogae mogg aparecem na saída do GetEnumNames(), mas a saída de GetEnumValues() apenas mostra ogg. A mesma coisa acontece para jpg, jpege mpg, mpeg. O nome que o PowerShell retorna para valores de sinônimo 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 enum 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 para 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 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 chamada ConvertTo-LineEndingRegex de instrução 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 inválido ou um valor numérico 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 armazenar 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 {0} de formato é substituído por um nome de tipo integral, o modelo cria um bloco de script 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 bloco de script 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 enum, 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 de cadeia de caracteres formatada para um determinado tipo de enumeração, valor de enumeração e cadeia de caracteres de formato. A saída é o mesmo 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 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 ou , ou , ou , e xF ou f. XdDgG 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 reflection 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 reflection retorna os nomes para 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 reflection 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 reflection retorna cada valor definido 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 cada valor definido 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 é 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 do sinalizador 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

IsDefined

O IsDefined() método estático retorna $true se o valor de entrada é definido para a enumeração e de outra forma $false. Use esse método para verificar se um valor é válido para uma enumeração sem precisar manipular erros de argumento inválido.

Você pode usar o método estático no tipo de classe base System.Enum ou 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 de um valor de enumeração. Esse método também é o modo de 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 do 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 com Gray como sinônimo Greyde . Em seguida, ele gera objetos que mostram o valor de enum real, o enum como uma cadeia de caracteres e o enum 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ê fizer 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 de um valor de sinônimo convertido em um nome específico. Você pode escrever código de forma confiável que converte uma cadeia de caracteres de sinônimo para o valor de enumeração. Ao trabalhar com o próprio valor de enumeração, sempre o compare 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 de 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 bit 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 do que o rótulo anterior.

Você pode definir valores para combinações de sinalizadores comumente usadas para facilitar aos usuários a especificação de um conjunto de sinalizadores de uma só vez. O nome para o 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 mostrando 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 um enum como seu tipo. Quando você especifica um enum como o tipo de um parâmetro, os usuários obtêm conclusão automática e validação do valor do parâmetro. A conclusão do argumento sugere a lista de rótulos válidos para o enum.

Quando um parâmetro tem um enum como tipo, você pode especificar qualquer um de:

  • 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 mostrando o comportamento de um parâmetro do tipo 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 para 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 ( ou , ou , ou , X e xF ou f ) para converter cada membro da enumeração TaskState em suas representações de cadeia de caracteres.dDgG

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 e F format exibem a lista de sinalizadores de conjunto para o valor delimitado com vírgulas. O último valor, 8, não lista nenhum sinalizador porque na verdade não é um conjunto de sinalizadores válido. Não é possível combinar os sinalizadores de enumeração para obter uma soma de 8 sem duplicar pelo menos um sinalizador.

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

Não é possível 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 do 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 lança 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 o IntelliSense e sugestões de 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. Verifique se a $ExportableTypes variável contém cada um dos tipos que você deseja disponibilizar aos usuários quando eles importam 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 manualmente enumerações 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 dot-sourced 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 using instrução, consulte about_Using.

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, em seguida, carregar a nova versão do módulo usando Import-Module com 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ê está 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 função em um arquivo que usa enumerações definidas em outro módulo, você deve usar a using module instrução para garantir que as funções tenham as definições de enumeração necessárias.

Limitações

  • Não é possível decorar valores de enumeração definidos no PowerShell com atributos. Você só pode decorar a própria declaração de enumeração, 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 oferece 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.