about_Enum
Breve descrição
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 ter que analisar ou verificar se há erros ortográficos.
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 assumem 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>]
...
}
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 à 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 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 que são iguais ao valor de uma enumeração retorna essa enumeração. A transmissã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; ver os valores construídos para: ogg
, oga
, mogg
, ou jpg
, jpeg
ou , 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
Nota
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
aparecerá na saída de GetEnumNames()
, mas a saída de GetEnumValues()
apenas mostra ogg
. O mesmo acontece com jpg
, jpeg
, e 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 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 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 chamando ConvertTo-LineEndingRegex
passa o valor de enumeração para CR
. A segunda instrução passa a cadeia de caracteres 'CRLF'
, que é convertida para um LineEnding. A terceira instrução especifica o valor 2
para o parâmetro, que mapeia 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 para formato {0}
é substituído por um nome de tipo integral, o modelo cria um bloco de script 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 loops 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.
Formato
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 é a mesma que chamar o método ToString no valor com a cadeia de caracteres de formato especificado.
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 F
ou f
.x
X
d
D
g
G
Para obter mais informações, consulte Enumeration Format Strings.
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 para 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 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 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 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 este método é mais curto e mais 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 caso contrário $false
. Use esse método para verificar se um valor é válido para uma enumeração sem a necessidade de manipular erros de argumento inválidos.
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 para um valor de enumeração.
Esse método também é o modo de exibição padrão para 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.
Nota
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 com Gray
como sinônimo de Grey
. Em seguida, ele produz objetos que mostram o valor real do eno, 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ê 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 de um valor de sinônimo convertido em um nome específico. Você pode escrever de forma confiável o código 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 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 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 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 mais alto do que o rótulo anterior.
Você pode definir valores para combinações de sinalizadores comumente usados para facilitar que os usuários especifiquem um conjunto de sinalizadores de uma só vez. O nome do valor deve ser os nomes combinados das bandeiras. 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 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 tipo. Quando você especifica um enum como o tipo para um parâmetro, os usuários obtêm conclusão automática e validação do valor do parâmetro. O preenchimento 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 digitado por 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 completo do tipo:
byte
- System.Bytesbyte
- System.SByteshort
- Sistema.Int16ushort
- Sistema.UInt16int
- Sistema.Int32uint
- Sistema.UInt32long
- Sistema.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 seguintes definições são funcionalmente idênticas. Apenas 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 Enumeration Format Strings.
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 e F
formato exibem a lista de sinalizadores definidos para o valor delimitado com vírgulas. O último valor, 8
, não lista nenhum sinalizador porque não é realmente 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.
Nota
Adicionar 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 gera um erro se já existir um acelerador de tipo com o mesmo nome quando você importa 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. Isso 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 quaisquer definições 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 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 dot-sourced para o 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 de funções no módulo raiz. Import-Module
não recarrega nenhum módulo aninhado. Além disso, não há como carregar classes atualizadas.
Para garantir que está a executar a versão mais recente, tem de iniciar uma nova sessão.
As classes e enumerações definidas no PowerShell e importadas com uma using
instrução não podem ser descarregadas.
Outra prática de desenvolvimento comum é 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 que sã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 com o FlagsAttribute para definir uma enumeração como um conjunto de sinalizadores de bits.
Alternativa: nenhuma
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.