about_Enum
Descripción breve
La enum
instrucción declara una enumeración. Una enumeración es un tipo distinto que consta de un conjunto de etiquetas con nombre denominada lista de enumeradores.
Descripción larga
La enum
instrucción permite crear un conjunto fuertemente tipado de etiquetas. Puede usar esa enumeración en el código sin tener que analizar ni comprobar si hay errores ortográficos.
Las enumeraciones se representan internamente como tipos de valor entero con un valor inicial de cero. De forma predeterminada, las enumeraciones de PowerShell usan System.Int32 ([int]
) como tipo subyacente. De forma predeterminada, PowerShell asigna la primera etiqueta de la lista el valor cero. De forma predeterminada, PowerShell asigna las etiquetas restantes con enteros consecutivos.
En la definición, puede asignar etiquetas a cualquier valor entero. Las etiquetas sin ningún valor asignado toman el siguiente valor entero.
Sintaxis
Las enumeraciones usan las sintaxis siguientes:
Sintaxis de definición de enumeración de enteros
[[<attribute>]...] enum <enum-name> {
<label> [= <int-value>]
...
}
Sintaxis de definición de enumeración de tipos subyacentes específica
[[<attribute>]...] enum <enum-name> : <underlying-type-name> {
<label> [= <int-value>]
...
}
Sintaxis de definición de enumeración de marcas
[[<attribute>]...] [Flag()] enum <enum-name>[ : <underlying-type-name>] {
<label 0> [= 1]
<label 1> [= 2]
<label 2> [= 4]
<label 3> [= 8]
...
...
}
Sintaxis de acceso de enumeración
[<enum-name>]::<label>
Ejemplos
Ejemplo 1: enumeración mínima
El siguiente bloque de código define la enumeración MarkdownUnorderedListCharacter con tres etiquetas. No asigna valores explícitos a ninguna etiqueta.
enum MarkdownUnorderedListCharacter {
Asterisk
Dash
Plus
}
El siguiente bloque de código muestra cómo se comportan los valores enteros y de cadena cuando se convierten en el tipo de enumeración.
$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
La conversión de enteros que son iguales al valor de una enumeración devuelve esa enumeración. La conversión de cadenas que son iguales que la etiqueta de una enumeración devuelve esa enumeración.
Ejemplo 2: Valores explícitos y de enumeración de sinónimos
En el ejemplo siguiente se muestra una enumeración de objetos que se correlacionan con los archivos multimedia. La definición asigna valores explícitos a los valores subyacentes de music
, picture
, video
. Las etiquetas inmediatamente después de una asignación explícita obtienen el siguiente valor entero. Puede crear sinónimos asignando el mismo valor a otra etiqueta; vea los valores construidos para: ogg
, oga
, mogg
o jpg
jpeg
, o mpg
, 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
}
El GetEnumNames()
método devuelve la lista de etiquetas de la enumeración.
[MediaTypes].GetEnumNames()
unknown
music
mp3
aac
ogg
oga
mogg
picture
jpg
jpeg
png
video
mpg
mpeg
avi
m4v
El GetEnumValues()
método devuelve la lista de los valores de la enumeración.
[MediaTypes].GetEnumValues()
unknown
music
mp3
aac
ogg
ogg
ogg
picture
jpg
jpg
png
video
mpg
mpg
avi
m4v
Nota:
GetEnumNames()
y GetEnumValues()
parecen devolver los mismos resultados; una lista de valores con nombre. Sin embargo, internamente, GetEnumValues()
enumera los valores y, a continuación, asigna valores a nombres. Lea cuidadosamente la lista y observará que ogg
, oga
y mogg
aparecen en la salida de GetEnumNames()
, pero la salida de GetEnumValues()
solo muestra ogg
. Lo mismo sucede con jpg
, jpeg
y mpg
, mpeg
. El nombre que PowerShell devuelve para los valores de sinónimo no es determinista.
Puede usar el GetEnumName()
método para obtener un nombre asociado a un valor específico. Si hay varios nombres asociados a un valor, el método devuelve el nombre definido por primera vez.
[MediaTypes].GetEnumName(15)
ogg
En el ejemplo siguiente se muestra cómo asignar cada nombre a su 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
Puede especificar un único valor de enumeración por su etiqueta con la sintaxis [<enum-name>]::<label>
.
[MediaTypes]::png
[MediaTypes]::png -eq 22
png
True
Ejemplo 3: enumeración como marcas
El siguiente bloque de código crea la enumeración FileAttributes como un conjunto de marcas de bits. El valor de cada etiqueta es el doble del valor de la etiqueta 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 probar si se establece una marca específica, puede usar el operador -band
de comparación binario . En este ejemplo se comprueban los atributos Device y Archive en el valor de $file2
.
PS > ($file2 -band [FileAttributes]::Device) -eq [FileAttributes]::Device
True
PS > ($file2 -band [FileAttributes]::Archive) -eq [FileAttributes]::Archive
False
También puede usar el HasFlag()
método para probar si se establece una marca específica.
En este ejemplo se comprueban los atributos Device y Hidden en el valor de $file1
.
PS > $file1.HasFlag([FileAttributes]::Device)
True
PS > $file1.HasFlag([FileAttributes]::Hidden)
False
Ejemplo 4: Enumeración como parámetro
En el ejemplo siguiente, la función ConvertTo-LineEndingRegex
define el parámetro InputObject con el 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
En el ejemplo, la primera instrucción que llama ConvertTo-LineEndingRegex
pasa el valor de enumeración para CR
. La segunda instrucción pasa la cadena 'CRLF'
, que se convierte en lineEnding. La tercera instrucción especifica el valor 2
del parámetro , que se asigna a la LF
etiqueta.
Puede ver las opciones de finalización de argumentos escribiendo el texto siguiente en el símbolo del sistema de PowerShell:
ConvertTo-LineEndingRegex -InputObject <Tab>
Al especificar un nombre de etiqueta no válido o un valor numérico para el parámetro , la función genera un error.
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".
Ejemplo 5: enumeraciones con tipos subyacentes específicos
A partir de PowerShell 6.2, puede definir enumeraciones con un tipo subyacente específico. En este ejemplo se muestran los tipos subyacentes válidos para una enumeración.
El primer bloque de código inicializa dos variables como matrices. $EnumTypes
es una matriz vacía que contiene los tipos creados dinámicamente. $IntegralTypes
es una matriz que contiene los tipos subyacentes válidos para una enumeración.
$EnumTypes = @()
$IntegralTypes = @(
'byte', 'sbyte', 'short', 'ushort', 'int', 'uint', 'long', 'ulong'
)
El siguiente bloque de código define una plantilla que se usará para crear dinámicamente las definiciones de enumeración. Cuando el {0}
marcador de posición de formato se reemplaza por un nombre de tipo entero, la plantilla crea un scriptblock que:
Define una enumeración denominada
<type>Enum
, comobyteEnum
. La enumeración definida usa el tipo entero especificado como tipo de valor subyacente.La enumeración se define con el
Min
valor establecido en el valor mínimo para el tipo entero. Define elMax
valor establecido en el valor máximo para el tipo entero.Devuelve el tipo recién definido.
$DefinitionTemplate = @"
enum {0}Enum : {0} {{
Min = [{0}]::MinValue
Max = [{0}]::MaxValue
}}
[{0}Enum]
"@
El siguiente bloque de código usa la plantilla para crear e invocar un scriptblock en el ámbito actual. Agrega las definiciones de tipo devueltas a la $EnumTypes
matriz.
foreach ($IntegralType in $IntegralTypes) {
$Definition = $DefinitionTemplate -f $IntegralType
$ScriptBlock = [scriptblock]::Create($Definition)
$EnumTypes += . $ScriptBlock
}
El último bloque de código recorre en bucle los tipos de enumeración mediante el GetEnumValuesAsUnderlyingType()
método para enumerar los valores como el tipo subyacente. El bucle crea un nuevo objeto para cada valor, que muestra el tipo de enumeración, el tipo de valor, la etiqueta y el 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 enumeración
En la lista siguiente se incluyen métodos útiles disponibles para enumeraciones en PowerShell y cómo usarlos.
Format
El Format()
método estático devuelve la salida de cadena con formato para un tipo de enumeración determinado, un valor de enumeración y una cadena de formato. La salida es la misma que llamar al método ToString en el valor con la cadena de formato especificada.
Puede usar el método estático en el tipo de clase base System.Enum o en un tipo de enumeración específico.
[System.Enum]::format([<enum-name>], <value>, <format-string>)
[<enum-name>]::format([<enum-name>], <value>, <format-string>)
Las cadenas de formato válidas son G
o g
, D
o X
d
, o x
, y F
o f
. Para obtener más información, vea Enumeration Format Strings( Cadenas de formato de enumeración).
En el ejemplo siguiente se usa cada una de las cadenas de formato de enumeración admitidas para convertir cada valor de la enumeración TaskState en sus representaciones de cadena.
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
El GetEnumName()
método de reflexión devuelve el nombre de un valor de enumeración específico. El valor de entrada debe ser un tipo subyacente válido para una enumeración, como un entero o un valor de enumeración. Si hay varios nombres asociados a un valor, el método devuelve el nombre definido por primera vez.
[<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
El GetEnumNames()
método de reflexión devuelve los nombres de cada valor de enumeración como cadenas. La salida incluye sinónimos.
[<enum-name>].GetEnumNames()
enum Season {
Unknown
Spring
Summer
Autumn
Winter
Fall = 3
}
[Season].GetEnumNames()
Unknown
Spring
Summer
Fall
Autumn
Winter
GetEnumUnderlyingType
El GetEnumUnderlyingType()
método de reflexión devuelve el tipo subyacente para los valores de enumeración.
[<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
El GetEnumValues()
método de reflexión devuelve todos los valores definidos para la enumeración.
[<enum-name>].GetEnumValues()
enum Season {
Unknown
Spring
Summer
Autumn
Winter
Fall = 3
}
[Season].GetEnumValues()
Unknown
Spring
Summer
Fall
Fall
Winter
GetEnumValuesAsUnderlyingType
El GetEnumValuesAsUnderlyingType()
método de reflexión devuelve todos los valores definidos para la enumeración como el tipo subyacente.
[<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
El HasFlag
método de instancia determina si se establece una marca de bits para un valor de enumeración de marcas. El uso de este método es más corto y fácil de leer que realizar una comparación binaria y una comprobación de equivalencia.
<enum-value>.HasFlag(<enum-flag-value>)
En el ejemplo siguiente se define la enumeración de marcas ModuleFeatures y se muestran las marcas que tiene el valor 39
.
[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
El IsDefined()
método estático devuelve $true
si el valor de entrada se define para la enumeración y, de lo contrario, $false
. Use este método para comprobar si un valor es válido para una enumeración sin necesidad de controlar errores de argumento no válidos.
Puede usar el método estático en el tipo de clase base System.Enum o en un tipo de enumeración 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
El ToString()
método de instancia devuelve la etiqueta de un valor de enumeración.
Este método también es la vista predeterminada de cómo se muestra un valor de enumeración como salida. Opcionalmente, puede especificar una cadena de formato para controlar cómo se muestra el valor. Para obtener más información sobre el formato, vea Formato de valores de enumeración.
Nota:
Para las enumeraciones que definen sinónimos para un valor específico, no escriba código que dependa de la salida de ToString()
. El método puede devolver cualquier nombre válido para el valor.
<enum-value>.ToString([<format-string>])
En el ejemplo siguiente se define la enumeración Shade con Gray
como sinónimo de Grey
. A continuación, genera objetos que muestran el valor de enumeración real, la enumeración como una cadena y la enumeración como un entero.
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 enumeración
Puede definir enumeraciones que asignen nombres diferentes al mismo valor entero. Cuando lo hace, los nombres que apuntan al mismo valor subyacente se denominan sinónimos. Las enumeraciones con sinónimos permiten a los usuarios especificar nombres diferentes para el mismo valor.
Al definir una enumeración con sinónimos, no escriba código que dependa de un valor de sinónimo que se convierta en un nombre específico. Puede escribir código de forma confiable que convierta una cadena de sinónimo en el valor de enumeración. Al trabajar con el propio valor de enumeración, compárelo siempre como un valor de enumeración o su tipo subyacente en lugar de como una cadena.
El siguiente bloque de código define la enumeración Shade con Grey
y 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
Enumeraciones como marcas
Un uso común de una enumeración es representar un conjunto de valores mutuamente excluyentes. Por ejemplo, una instancia de ArrivalStatus puede tener un valor de Early, OnTime o Late. No tiene sentido que el valor de una instancia de ArrivalStatus refleje más de una constante de enumeración.
Sin embargo, en otros casos, el valor de un objeto de enumeración puede incluir varios miembros de enumeración y cada miembro representa un campo de bits en el valor de enumeración. Puede usar FlagsAttribute para indicar que la enumeración consta de campos de bits como marcas que los usuarios pueden combinar.
Para que las enumeraciones como marcas funcionen correctamente, debe establecer el valor entero de cada etiqueta en una potencia de dos. Si no especifica un valor para una etiqueta, PowerShell establece el valor en uno superior a la etiqueta anterior.
Puede definir valores para combinaciones de marcas usadas habitualmente para facilitar a los usuarios especificar un conjunto de marcas a la vez. El nombre del valor debe ser los nombres combinados de las marcas. El valor entero debe ser la suma de los valores de marca.
Para determinar si se establece una marca específica para un valor, use el HasFlag()
método en el valor o use el operador -band
de comparación binario .
Para ver un ejemplo en el que se muestra cómo usar enumeraciones de marcas y comprobar si se establece una marca, vea Ejemplo 3.
Enumeraciones como parámetros
Puede definir parámetros de cmdlet que usen una enumeración como su tipo. Cuando se especifica una enumeración como el tipo de un parámetro, los usuarios obtienen la finalización automática y validación del valor del parámetro. La finalización del argumento sugiere la lista de etiquetas válidas para la enumeración.
Cuando un parámetro tiene una enumeración como su tipo, puede especificar cualquiera de:
- Una enumeración, como
[<EnumType>]::<Label>
- Etiqueta de una enumeración como una cadena
- Valor numérico de una enumeración
Para ver un ejemplo que muestra el comportamiento de un parámetro con tipo de enumeración, vea Ejemplo 4.
Enumeraciones con tipos subyacentes específicos
A partir de PowerShell 6.2, puede definir enumeraciones con un tipo subyacente específico. Al definir una enumeración sin un tipo subyacente específico, PowerShell crea la enumeración con [int]
(System.Int32) como el tipo subyacente.
El tipo subyacente de una enumeración debe ser un tipo numérico entero. En la lista siguiente se incluyen los tipos válidos con su nombre corto y el nombre de tipo completo:
byte
- System.Bytesbyte
- System.SByteshort
- System.Int16ushort
- System.UInt16int
- System.Int32uint
- System.UInt32long
- System.Int64ulong
- System.UInt64
Puede definir un tipo subyacente específico para la enumeración como el nombre corto o el nombre de tipo completo. Las definiciones siguientes son funcionalmente idénticas. Solo el nombre usado para el tipo subyacente es diferente.
enum LongValueEnum : long {
Zero
One
Two
}
enum LongValueEnum : System.Int64 {
Zero
One
Two
}
Aplicar formato a los valores de enumeración
Puede convertir los valores de enumeración en sus representaciones de cadena llamando al método static Format, así como a las sobrecargas del método ToString de instancia. Puede usar una cadena de formato para controlar la forma precisa en que un valor de enumeración se representa como una cadena. Para obtener más información, vea Enumeration Format Strings( Cadenas de formato de enumeración).
En el ejemplo siguiente se usa cada una de las cadenas de formato de enumeración admitidas (G
o g
D
, o d
, X
o x
y F
o f
) para convertir cada miembro de la enumeración TaskState en sus representaciones de cadena.
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
En el ejemplo siguiente se usan las cadenas de formato para los valores de una enumeración de marcas.
[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 las enumeraciones de marcas, las G
cadenas de formato y F
muestran la lista de marcas establecidas para el valor delimitado con comas. El último valor, 8
, no muestra ninguna marca porque no es realmente un conjunto de marcas válido. No se pueden combinar las marcas de enumeración para obtener una suma de 8
sin duplicar al menos una marca.
Definición de métodos de extensión con Update-TypeData
No se pueden definir métodos en la declaración de una enumeración. Para ampliar la funcionalidad de una enumeración, puede usar el cmdlet Update-TypeData para definir ScriptMethod
miembros para la enumeración.
En el ejemplo siguiente se usa el Update-TypeData
cmdlet para agregar un GetFlags()
método a la enumeración de marcas FileAttributes . Devuelve una matriz de las marcas establecidas para el 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
Exportación de enumeraciones con aceleradores de tipos
De forma predeterminada, los módulos de PowerShell no exportan automáticamente clases y enumeraciones definidas en PowerShell. Los tipos personalizados no están disponibles fuera del módulo sin llamar a una using module
instrucción .
Sin embargo, si un módulo agrega aceleradores de tipos, esos aceleradores de tipos están disponibles inmediatamente en la sesión después de que los usuarios importen el módulo.
Nota:
Agregar aceleradores de tipos a la sesión usa una API interna (no pública). El uso de esta API puede provocar conflictos. El patrón descrito a continuación produce un error si ya existe un acelerador de tipos con el mismo nombre al importar el módulo. También quita los aceleradores de tipos al quitar el módulo de la sesión.
Este patrón garantiza que los tipos están disponibles en una sesión. No afecta a IntelliSense ni a la finalización al crear un archivo de script en VS Code.
Para obtener intelliSense y sugerencias de finalización para tipos personalizados en VS Code, debe agregar una using module
instrucción a la parte superior del script.
El siguiente patrón muestra cómo puede registrar clases y enumeraciones de PowerShell como aceleradores de tipos en un módulo. Agregue el fragmento de código al módulo de script raíz después de cualquier definición de tipo. Asegúrese de que la $ExportableTypes
variable contiene cada uno de los tipos que desea que estén disponibles para los usuarios cuando importen el módulo. El otro código no requiere ninguna edición.
# 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()
Cuando los usuarios importan el módulo, los tipos agregados a los aceleradores de tipos para la sesión están disponibles inmediatamente para IntelliSense y la finalización. Cuando se quita el módulo, por lo que son los aceleradores de tipos.
Importación manual de enumeraciones desde un módulo de PowerShell
Import-Module
y la #requires
instrucción solo importan las funciones, alias y variables del módulo, tal como se define en el módulo. No se importan las enumeraciones.
Si un módulo define clases y enumeraciones, pero no agrega aceleradores de tipos para esos tipos, use una using module
instrucción para importarlas.
La using module
instrucción importa clases y enumeraciones desde el módulo raíz (ModuleToProcess
) de un módulo de script o un módulo binario. No importa de forma coherente las clases definidas en módulos anidados o clases definidas en scripts con origen de puntos en el módulo raíz. Defina las clases que desea que estén disponibles para los usuarios fuera del módulo directamente en el módulo raíz.
Para obtener más información sobre la using
instrucción , consulte about_Using.
Carga del código recién cambiado durante el desarrollo
Durante el desarrollo de un módulo de script, es habitual realizar cambios en el código y, a continuación, cargar la nueva versión del módulo mediante Import-Module
con el parámetro Force . Esto funciona solo para los cambios en las funciones del módulo raíz. Import-Module
no vuelve a cargar ningún módulo anidado. Además, no hay forma de cargar ninguna clase actualizada.
Para asegurarse de que ejecuta la versión más reciente, debe iniciar una nueva sesión.
Las clases y enumeraciones definidas en PowerShell y importadas con una using
instrucción no se pueden descargar.
Otra práctica de desarrollo común es separar el código en archivos diferentes. Si tiene una función en un archivo que usa enumeraciones definidas en otro módulo, debe usar la using module
instrucción para asegurarse de que las funciones tienen las definiciones de enumeración necesarias.
Limitaciones
No se pueden decorar los valores de enumeración definidos en PowerShell con atributos. Solo puede decorar la declaración de enumeración, como con FlagsAttribute para definir una enumeración como un conjunto de marcas de bits.
Solución alternativa: ninguna
No se pueden definir métodos dentro de definiciones de enumeración y PowerShell no admite la definición de [métodos de extensión] como C#.
Solución alternativa: use el cmdlet Update-TypeData para definir
ScriptMethod
miembros para la enumeración.