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
, , jpg
ou mpg
, jpeg
mpeg
, , .
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 ogg
apenas . 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 -band
de 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:
Define uma enumeração chamada
<type>Enum
, comobyteEnum
. 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 oMax
valor definido como o valor máximo para o tipo integral.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 -band
de 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.Bytesbyte
- System.SByteshort
- System.Int16ushort
- System.UInt16int
- System.Int32uint
- System.UInt32long
- System.Int64ulong
- 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.