Partager via


À propos de l’énumération

Description courte

L’instruction enum déclare une énumération. Une énumération est un type distinct qui se compose d’un ensemble d’étiquettes nommées appelées liste d’énumérateurs.

Description longue

L’instruction enum vous permet de créer un ensemble fortement typé d’étiquettes. Vous pouvez utiliser cette énumération dans le code sans avoir à analyser ou vérifier les erreurs d’orthographe.

Les énumérations sont représentées en interne en tant que types de valeurs intégrales avec une valeur de départ de zéro. Par défaut, les énumérations PowerShell utilisent System.Int32 ([int]) comme type sous-jacent. Par défaut, PowerShell affecte la première étiquette de la liste zéro. Par défaut, PowerShell affecte les étiquettes restantes avec des entiers consécutifs.

Dans la définition, vous pouvez attribuer des étiquettes n’importe quelle valeur entière. Les étiquettes sans valeur affectée prennent la valeur entière suivante.

Syntaxe

Les énumérations utilisent les syntaxes suivantes :

Syntaxe de définition d’énumération entière

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

Syntaxe de définition d’énumération de type sous-jacente spécifique

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

Syntaxe de définition d’énumération d’indicateur

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

Syntaxe d’accès aux énumérations

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

Exemples

Exemple 1 - Énumération minimale

Le bloc de code suivant définit l’énumération MarkdownUnorderedListCharacter avec trois étiquettes. Elle n’affecte pas de valeurs explicites à une étiquette.

enum MarkdownUnorderedListCharacter {
    Asterisk
    Dash
    Plus
}

Le bloc de code suivant montre comment les valeurs entières et de chaînes se comportent lors de la conversion vers le type d’énumération.

$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 conversion d’entiers qui sont égaux à la valeur d’une énumération retourne cette énumération. La conversion de chaînes identiques à l’étiquette d’une énumération retourne cette énumération.

Exemple 2 - Valeurs d’énumération explicites et synonymes

L’exemple suivant montre une énumération d’objets qui sont corrélés aux fichiers multimédias. La définition affecte des valeurs explicites aux valeurs sous-jacentes de music, picturevideo. Les étiquettes qui suivent immédiatement une affectation explicite obtiennent la valeur entière suivante. Vous pouvez créer des synonymes en affectant la même valeur à une autre étiquette ; consultez les valeurs construites pour : ogg, , moggoga, jpegou jpg, ou 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
}

La GetEnumNames() méthode retourne la liste des étiquettes de l’énumération.

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

La GetEnumValues() méthode retourne la liste des valeurs de l’énumération.

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

Remarque

GetEnumNames() et GetEnumValues() semblent retourner les mêmes résultats ; une liste de valeurs nommées. Toutefois, en interne, GetEnumValues() énumère les valeurs, puis mappe les valeurs en noms. Lisez attentivement la liste et vous remarquerez que , et apparaissent dans la sortie de GetEnumNames(), mais la sortie de GetEnumValues() seulement s’affiche ogg.mogg ogaogg La même chose se produit pour jpg, jpeget mpg, mpeg. Le nom que PowerShell retourne pour les valeurs de synonymes n’est pas déterministe.

Vous pouvez utiliser la GetEnumName() méthode pour obtenir un nom associé à une valeur spécifique. S’il existe plusieurs noms associés à une valeur, la méthode retourne le prénom défini.

[MediaTypes].GetEnumName(15)
ogg

L’exemple suivant montre comment mapper chaque nom à sa valeur.

[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

Vous pouvez spécifier une valeur d’énumération unique par son étiquette avec la syntaxe [<enum-name>]::<label>.

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

Exemple 3 - Énumération sous forme d’indicateurs

Le bloc de code suivant crée l’énumération FileAttributes en tant qu’ensemble d’indicateurs de bits. La valeur de chaque étiquette est double de la valeur de l’étiquette précédente.

[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

Pour tester si un indicateur spécifique est défini, vous pouvez utiliser l’opérateur -bandde comparaison binaire . Cet exemple teste les attributs Device et Archive dans la valeur de $file2.

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

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

Vous pouvez également utiliser la HasFlag() méthode pour tester si un indicateur spécifique est défini. Cet exemple teste les attributs Device et Hidden dans la valeur de $file1.

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

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

Exemple 4 - Énumération en tant que paramètre

Dans l’exemple suivant, la fonction ConvertTo-LineEndingRegex définit le paramètre InputObject avec le type 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

Dans l’exemple, la première instruction appelant ConvertTo-LineEndingRegex transmet la valeur d’énumération pour CR. La deuxième instruction transmet la chaîne 'CRLF', qui est convertie en LineEnding. La troisième instruction spécifie la valeur 2 du paramètre, qui correspond à l’étiquette LF .

Vous pouvez voir les options de saisie semi-automatique des arguments en tapant le texte suivant dans votre invite PowerShell :

ConvertTo-LineEndingRegex -InputObject <Tab>

Lorsque vous spécifiez un nom d’étiquette ou une valeur numérique non valide pour le paramètre, la fonction génère une erreur.

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".

Exemple 5 - Énumérations avec des types sous-jacents spécifiques

À compter de PowerShell 6.2, vous pouvez définir des énumérations avec un type sous-jacent spécifique. Cet exemple montre les types sous-jacents valides pour une énumération.

Le premier bloc de code initialise deux variables sous forme de tableaux. $EnumTypes est un tableau vide pour contenir les types créés dynamiquement. $IntegralTypes est un tableau qui contient les types sous-jacents valides pour une énumération.

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

Le bloc de code suivant définit un modèle à utiliser pour créer dynamiquement les définitions d’énumération. Lorsque l’espace réservé au {0} format est remplacé par un nom de type intégral, le modèle crée un scriptblock qui :

  1. Définit une énumération nommée <type>Enum, comme byteEnum. L’énumération définie utilise le type intégral spécifié comme type valeur sous-jacent.

    L’énumération est définie avec la Min valeur définie sur la valeur minimale pour le type intégral. Elle définit la Max valeur définie sur la valeur maximale pour le type intégral.

  2. Retourne le type nouvellement défini.

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

[{0}Enum]
"@

Le bloc de code suivant utilise le modèle pour créer et appeler un scriptblock dans l’étendue actuelle. Il ajoute les définitions de type retournées dans le $EnumTypes tableau.

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

La dernière boucle de bloc de code sur les types d’énumération, à l’aide de la GetEnumValuesAsUnderlyingType() méthode pour répertorier les valeurs comme type sous-jacent. La boucle crée un objet pour chaque valeur, affichant le type d’énumération, le type valeur, l’étiquette et la valeur réelle.

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éthodes d’énumération

La liste suivante inclut des méthodes utiles disponibles pour les énumérations dans PowerShell et leur utilisation.

Format

La Format() méthode statique retourne la sortie de chaîne mise en forme pour un type d’énumération donné, une valeur d’énumération et une chaîne de format. La sortie est identique à l’appel de la méthode ToString sur la valeur avec la chaîne de format spécifiée.

Vous pouvez utiliser la méthode statique sur le type de classe de base System.Enum ou un type d’énumération spécifique.

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

Les chaînes de format valides sont ou , ou , ou , et F ou f.xX dD gG Pour plus d’informations, consultez Chaînes de format d’énumération.

L’exemple suivant utilise chacune des chaînes de format d’énumération prises en charge pour convertir chaque valeur de l’énumération TaskState en ses représentations sous forme de chaîne.

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

La GetEnumName() méthode de réflexion retourne le nom d’une valeur d’énumération spécifique. La valeur d’entrée doit être un type sous-jacent valide pour une énumération, comme un entier ou une valeur d’énumération. S’il existe plusieurs noms associés à une valeur, la méthode retourne le prénom défini.

[<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

La GetEnumNames() méthode de réflexion retourne les noms de chaque valeur d’énumération sous forme de chaînes. La sortie inclut des synonymes.

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

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

GetEnumUnderlyingType

La GetEnumUnderlyingType() méthode de réflexion retourne le type sous-jacent pour les valeurs d’énumération.

[<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

La GetEnumValues() méthode de réflexion retourne chaque valeur définie pour l’énumération.

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

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

GetEnumValuesAsUnderlyingType

La GetEnumValuesAsUnderlyingType() méthode de réflexion retourne chaque valeur définie pour l’énumération comme type sous-jacent.

[<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

La HasFlag méthode d’instance détermine si un indicateur de bits est défini pour une valeur d’énumération d’indicateur. L’utilisation de cette méthode est plus courte et plus facile à lire que d’effectuer une comparaison binaire et une vérification d’équivalence.

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

L’exemple suivant définit l’énumération de l’indicateur ModuleFeatures et indique les indicateurs dont la valeur 39 a.

[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

La IsDefined() méthode statique retourne $true si la valeur d’entrée est définie pour l’énumération et sinon $false. Utilisez cette méthode pour vérifier si une valeur est valide pour une énumération sans avoir à gérer les erreurs d’argument non valides.

Vous pouvez utiliser la méthode statique sur le type de classe de base System.Enum ou un type d’énumération spécifique.

[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

La ToString() méthode d’instance retourne l’étiquette d’une valeur d’énumération. Cette méthode est également l’affichage par défaut de la façon dont une valeur d’énumération s’affiche comme sortie. Si vous le souhaitez, vous pouvez spécifier une chaîne de format pour contrôler l’affichage de la valeur. Pour plus d’informations sur la mise en forme, consultez Valeurs d’énumération de mise en forme.

Remarque

Pour les énumérations qui définissent des synonymes pour une valeur spécifique, n’écrivez pas de code qui dépend de la sortie de ToString(). La méthode peut retourner n’importe quel nom valide pour la valeur.

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

L’exemple suivant définit l’énumération Shade avec Gray comme synonyme de Grey. Il génère ensuite des objets qui affichent la valeur d’énumération réelle, l’énumération sous forme de chaîne et l’énumération sous forme d’entier.

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

Synonymes de valeur d’énumération

Vous pouvez définir des énumérations qui donnent des noms différents à la même valeur entière. Lorsque vous le faites, les noms qui pointent vers la même valeur sous-jacente sont appelés synonymes. Les énumérations avec synonymes permettent aux utilisateurs de spécifier des noms différents pour la même valeur.

Lorsque vous définissez une énumération avec des synonymes, n’écrivez pas de code qui dépend d’une valeur de synonyme convertie en un nom spécifique. Vous pouvez écrire de manière fiable du code qui convertit une chaîne de synonymes en valeur d’énumération. Lorsque vous utilisez la valeur d’énumération elle-même, comparez-la toujours en tant que valeur d’énumération ou son type sous-jacent au lieu d’une chaîne.

Le bloc de code suivant définit l’énumération Shade avec Grey et Gray en tant que synonymes.

enum Shade {
    White
    Grey
    Gray = 1
    Black
}

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

Énumérations en tant qu’indicateurs

L’une des utilisations courantes d’une énumération consiste à représenter un ensemble de valeurs mutuellement exclusives. Par exemple, une instance ArrivalStatus peut avoir la valeur Early, OnTime ou Late. Il n’est pas logique que la valeur d’une instance ArrivalStatus reflète plusieurs constantes d’énumération.

Dans d’autres cas, toutefois, la valeur d’un objet d’énumération peut inclure plusieurs membres d’énumération, et chaque membre représente un champ de bits dans la valeur d’énumération. Vous pouvez utiliser FlagsAttribute pour indiquer que l’énumération se compose de champs de bits en tant qu’indicateurs que les utilisateurs peuvent combiner.

Pour que les énumérations en tant qu’indicateurs fonctionnent correctement, vous devez définir la valeur entière de chaque étiquette sur une puissance de deux. Si vous ne spécifiez pas de valeur pour une étiquette, PowerShell définit la valeur sur une valeur supérieure à l’étiquette précédente.

Vous pouvez définir des valeurs pour les combinaisons d’indicateurs couramment utilisées pour faciliter la spécification d’un ensemble d’indicateurs à la fois. Le nom de la valeur doit être le nom combiné des indicateurs. La valeur entière doit être la somme des valeurs d’indicateur.

Pour déterminer si un indicateur spécifique est défini pour une valeur, utilisez la HasFlag() méthode sur la valeur ou utilisez l’opérateur -bandde comparaison binaire .

Pour obtenir un exemple montrant comment utiliser des énumérations d’indicateurs et vérifier si un indicateur est défini, consultez l’exemple 3.

Énumérations en tant que paramètres

Vous pouvez définir des paramètres d’applet de commande qui utilisent une énumération comme type. Lorsque vous spécifiez une énumération comme type pour un paramètre, les utilisateurs obtiennent la saisie semi-automatique pour et la validation de la valeur du paramètre. L’achèvement de l’argument suggère la liste des étiquettes valides pour l’énumération.

Lorsqu’un paramètre a une énumération en tant que type, vous pouvez spécifier l’un des éléments suivants :

  • Énumération, comme [<EnumType>]::<Label>
  • Étiquette d’une énumération sous forme de chaîne
  • Valeur numérique d’une énumération

Pour obtenir un exemple montrant le comportement d’un paramètre typé énumération, consultez l’exemple 4.

Énumérations avec des types sous-jacents spécifiques

À compter de PowerShell 6.2, vous pouvez définir des énumérations avec un type sous-jacent spécifique. Lorsque vous définissez une énumération sans type sous-jacent spécifique, PowerShell crée l’énumération avec [int] (System.Int32) comme type sous-jacent.

Le type sous-jacent d’une énumération doit être un type numérique intégral. La liste suivante inclut les types valides avec leur nom court et leur nom de type complet :

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

Vous pouvez définir un type sous-jacent spécifique pour l’énumération en tant que nom court ou nom de type complet. Les définitions suivantes sont fonctionnellement identiques. Seul le nom utilisé pour le type sous-jacent est différent.

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

Mise en forme des valeurs d’énumération

Vous pouvez convertir des valeurs d’énumération en leurs représentations sous forme de chaîne en appelant la méthode Format statique, ainsi que les surcharges de la méthode ToString de l’instance. Vous pouvez utiliser une chaîne de format pour contrôler la façon précise dont une valeur d’énumération est représentée sous forme de chaîne. Pour plus d’informations, consultez Chaînes de format d’énumération.

L’exemple suivant utilise chacune des chaînes de format d’énumération prises en charge (G ou g, D ou d, X ou x, et ou f F ) pour convertir chaque membre de l’énumération TaskState en ses représentations sous forme de chaînes.

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

L’exemple suivant utilise les chaînes de format pour les valeurs d’une énumération d’indicateur.

[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

Notez que pour les énumérations d’indicateurs, les G chaînes de F mise en forme affichent la liste des indicateurs définis pour la valeur délimitée par des virgules. La dernière valeur, 8ne répertorie aucun indicateur, car il n’est pas réellement un jeu d’indicateurs valide. Vous ne pouvez pas combiner les indicateurs d’énumération pour obtenir une somme d’au 8 moins un indicateur sans dupliquer au moins un indicateur.

Définition de méthodes d’extension avec Update-TypeData

Vous ne pouvez pas définir de méthodes dans la déclaration d’une énumération. Pour étendre les fonctionnalités d’une énumération, vous pouvez utiliser l’applet de commande Update-TypeData pour définir des ScriptMethod membres pour l’énumération.

L’exemple suivant utilise l’applet Update-TypeData de commande pour ajouter une GetFlags() méthode à l’énumération de l’indicateur FileAttributes . Elle retourne un tableau des indicateurs définis pour la valeur.

[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

Exportation d’énumérations avec accélérateurs de type

Par défaut, les modules PowerShell n’exportent pas automatiquement les classes et les énumérations définies dans PowerShell. Les types personnalisés ne sont pas disponibles en dehors du module sans appeler une using module instruction.

Toutefois, si un module ajoute des accélérateurs de type, ces accélérateurs de type sont immédiatement disponibles dans la session après l’importation du module par les utilisateurs.

Remarque

L’ajout d’accélérateurs de type à la session utilise une API interne (non publique). L’utilisation de cette API peut entraîner des conflits. Le modèle décrit ci-dessous génère une erreur si un accélérateur de type portant le même nom existe déjà lorsque vous importez le module. Il supprime également les accélérateurs de type lorsque vous supprimez le module de la session.

Ce modèle garantit que les types sont disponibles dans une session. Il n’affecte pas IntelliSense ou la saisie semi-automatique lors de la création d’un fichier de script dans VS Code. Pour obtenir des suggestions IntelliSense et de saisie semi-automatique pour les types personnalisés dans VS Code, vous devez ajouter une using module instruction en haut du script.

Le modèle suivant montre comment inscrire des classes et des énumérations PowerShell en tant qu’accélérateurs de type dans un module. Ajoutez l’extrait de code au module de script racine après toutes les définitions de type. Vérifiez que la $ExportableTypes variable contient chacun des types que vous souhaitez rendre accessibles aux utilisateurs lorsqu’ils importent le module. L’autre code ne nécessite aucune modification.

# 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()

Lorsque les utilisateurs importent le module, tous les types ajoutés aux accélérateurs de type pour la session sont immédiatement disponibles pour IntelliSense et la saisie semi-automatique. Lorsque le module est supprimé, il s’agit donc des accélérateurs de type.

Importation manuelle d’énumérations à partir d’un module PowerShell

Import-Module et l’instruction #requires importent uniquement les fonctions de module, les alias et les variables, comme défini par le module. Les énumérations ne sont pas importées.

Si un module définit des classes et des énumérations, mais n’ajoute pas d’accélérateurs de type pour ces types, utilisez une using module instruction pour les importer.

L’instruction using module importe des classes et des énumérations à partir du module racine (ModuleToProcess) d’un module de script ou d’un module binaire. Elle n’importe pas de manière cohérente les classes définies dans les modules imbriqués ou les classes définies dans les scripts qui sont sources par points dans le module racine. Définissez les classes que vous souhaitez mettre à la disposition des utilisateurs en dehors du module directement dans le module racine.

Pour plus d’informations sur l’instruction using , consultez about_Using.

Chargement du code nouvellement modifié pendant le développement

Pendant le développement d’un module de script, il est courant d’apporter des modifications au code, puis de charger la nouvelle version du module à l’aide Import-Module du paramètre Force . Cela fonctionne uniquement pour les modifications apportées aux fonctions dans le module racine. Import-Module ne recharge aucun module imbriqué. En outre, il n’existe aucun moyen de charger des classes mises à jour.

Pour vous assurer que vous exécutez la dernière version, vous devez démarrer une nouvelle session. Les classes et les énumérations définies dans PowerShell et importées avec une using instruction ne peuvent pas être déchargées.

Une autre pratique de développement courante consiste à séparer votre code en différents fichiers. Si vous avez une fonction dans un fichier qui utilise des énumérations définies dans un autre module, vous devez utiliser l’instruction using module pour vous assurer que les fonctions ont les définitions d’énumération nécessaires.

Limites

  • Vous ne pouvez pas décorer les valeurs d’énumération définies dans PowerShell avec des attributs. Vous pouvez uniquement décorer la déclaration d’énumération elle-même, comme avec FlagsAttribute pour définir une énumération en tant qu’ensemble d’indicateurs de bits.

    Solution de contournement : aucune

  • Vous ne pouvez pas définir de méthodes dans les définitions d’énumération et PowerShell ne prend pas en charge la définition de [méthodes d’extension] comme C#.

    Solution de contournement : utilisez l’applet de commande Update-TypeData pour définir des ScriptMethod membres pour l’énumération.