about_Enum

Krótki opis

Instrukcja enum deklaruje wyliczenie. Wyliczenie jest odrębnym typem, który składa się z zestawu nazwanych etykiet nazywanych listą modułów wyliczających.

Długi opis

Instrukcja enum umożliwia utworzenie silnie typizowanego zestawu etykiet. Tego wyliczenia można użyć w kodzie bez konieczności analizowania lub sprawdzania błędów pisowni.

Wyliczenia są wewnętrznie reprezentowane jako typy wartości całkowitych z początkową wartością zero. Domyślnie wyliczenia programu PowerShell używają elementu System.Int32 ([int]) jako typu bazowego. Domyślnie program PowerShell przypisuje pierwszą etykietę na liście wartość zero. Domyślnie program PowerShell przypisuje pozostałe etykiety z kolejnymi liczbami całkowitymi.

W definicji można nadać etykietom dowolną wartość całkowitą. Etykiety bez przypisanej wartości przyjmują następną wartość całkowitą.

Składnia

Wyliczenia używają następujących składni:

Składnia definicji wyliczenia liczb całkowitych

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

Składnia wyliczenia określonego typu bazowego

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

Składnia definicji wyliczenia flagi

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

Składnia dostępu do wyliczenia

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

Przykłady

Przykład 1 — minimalna wyliczenie

Poniższy blok kodu definiuje wyliczenie MarkdownUnorderedListCharacter z trzema etykietami. Nie przypisuje jawnych wartości do żadnej etykiety.

enum MarkdownUnorderedListCharacter {
    Asterisk
    Dash
    Plus
}

Następny blok kodu pokazuje, jak zachowują się zarówno wartości całkowite, jak i ciągowe podczas rzutowania do typu wyliczenia.

$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

Rzutowanie liczb całkowitych, które są równe wartości wyliczenia, zwraca ten wyliczenie. Rzutowanie ciągów, które są takie same jak etykieta wyliczenia, zwraca tę wyliczenie.

Przykład 2 — jawne i synonimowe wartości wyliczenia

W poniższym przykładzie przedstawiono wyliczenie obiektów skorelowanych z plikami multimedialnymi. Definicja przypisuje jawne wartości do bazowych wartości music, , picturevideo. Etykiety natychmiast po jawnym przypisaniu uzyskują następną wartość całkowitą. Synonimy można utworzyć, przypisując tę samą wartość do innej etykiety; Zobacz skonstruowane wartości dla: ogg, , ogamogg, lub mpgjpgjpeg, . 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
}

Metoda GetEnumNames() zwraca listę etykiet dla wyliczenia.

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

Metoda GetEnumValues() zwraca listę wartości wyliczenia.

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

Uwaga

GetEnumNames() i GetEnumValues() wydają się zwracać te same wyniki; lista nazwanych wartości. Jednak wewnętrznie GetEnumValues() wylicza wartości, a następnie mapuje wartości na nazwy. Uważnie odczytaj listę i zauważysz, że oggelement , ogai mogg pojawi się w danych wyjściowych GetEnumNames()GetEnumValues() polecenia , ale dane wyjściowe są wyświetlane oggtylko w pliku . Dzieje się tak samo w przypadku , jpgjpegi mpg, mpeg. Nazwa programu PowerShell zwraca wartość dla wartości synonimów nie jest deterministyczna.

Możesz użyć GetEnumName() metody , aby uzyskać nazwę skojarzona z określoną wartością. Jeśli istnieje wiele nazw skojarzonych z wartością, metoda zwraca pierwszą zdefiniowaną nazwę.

[MediaTypes].GetEnumName(15)
ogg

W poniższym przykładzie pokazano, jak zamapować każdą nazwę na jej wartość.

[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

Można określić pojedynczą wartość wyliczeniową według etykiety za pomocą składni [<enum-name>]::<label>.

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

Przykład 3 — Wyliczenie jako flagi

Poniższy blok kodu tworzy wyliczenie FileAttributes jako zestaw flag bitowych. Wartość dla każdej etykiety jest dwukrotnie częścią poprzedniej etykiety.

[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

Aby sprawdzić, czy ustawiono konkretną flagę, możesz użyć operatora -bandporównania binarnego . W tym przykładzie testuje atrybuty Device i Archive w wartości $file2.

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

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

Możesz również użyć HasFlag() metody , aby sprawdzić, czy ustawiono konkretną flagę. W tym przykładzie testuje atrybuty Urządzenie i Ukryte w wartości $file1.

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

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

Przykład 4 — Wyliczenie jako parametr

W poniższym przykładzie funkcja ConvertTo-LineEndingRegex definiuje parametr InputObject z typem 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

W tym przykładzie pierwsza instrukcja wywołująca ConvertTo-LineEndingRegex przekazuje wartość wyliczenia dla elementu CR. Druga instrukcja przekazuje ciąg 'CRLF', który jest rzutowy na lineEnding. Trzecia instrukcja określa wartość 2 parametru, który mapuje na etykietę LF .

Opcje uzupełniania argumentów można wyświetlić, wpisując następujący tekst w wierszu polecenia programu PowerShell:

ConvertTo-LineEndingRegex -InputObject <Tab>

Po określeniu nieprawidłowej nazwy etykiety lub wartości liczbowej parametru funkcja zgłasza błąd.

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

Przykład 5 — Wyliczenie z określonymi typami bazowymi

Począwszy od programu PowerShell 6.2, można zdefiniować wyliczenia z określonym typem bazowym. W tym przykładzie przedstawiono prawidłowe typy bazowe dla wyliczenia.

Pierwszy blok kodu inicjuje dwie zmienne jako tablice. $EnumTypes jest pustą tablicą do przechowywania dynamicznie utworzonych typów. $IntegralTypes jest tablicą zawierającą prawidłowe typy bazowe dla wyliczenia.

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

Następny blok kodu definiuje szablon używany do dynamicznego tworzenia definicji wyliczenia. {0} Gdy symbol zastępczy formatu zostanie zastąpiony nazwą typu całkowitego, szablon tworzy blok skryptu, który:

  1. Definiuje wyliczenie o nazwie <type>Enum, na przykład byteEnum. Zdefiniowane wyliczenie używa określonego typu całkowitego jako podstawowego typu wartości.

    Wyliczenie jest definiowane z wartością Min ustawioną na wartość minimalną dla typu całkowitego. Definiuje Max wartość ustawioną na wartość maksymalną dla typu całkowitego.

  2. Zwraca nowo zdefiniowany typ.

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

[{0}Enum]
"@

Następny blok kodu używa szablonu do utworzenia i wywołania blokady skryptu w bieżącym zakresie. Dodaje zwracane definicje typów do tablicy $EnumTypes .

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

Ostatni blok kodu wykonuje pętle na typach wyliczenia przy użyciu GetEnumValuesAsUnderlyingType() metody , aby wyświetlić wartości jako typ bazowy. Pętla tworzy nowy obiekt dla każdej wartości, pokazując typ wyliczenia, typ wartości, etykietę i rzeczywistą wartość.

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

Metody wyliczania

Poniższa lista zawiera przydatne metody dostępne do wyliczania w programie PowerShell i sposób ich używania.

Formatuj

Metoda statyczna Format() zwraca sformatowane dane wyjściowe ciągu dla danego typu wyliczenia, wartości wyliczenia i ciągu formatu. Dane wyjściowe są takie same jak wywołanie metody ToString dla wartości z określonym ciągiem formatu.

Można użyć metody statycznej w typie klasy bazowej System.Enum lub określonym typie wyliczenia.

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

Prawidłowe ciągi formatu to G , Dglub dX , lub xlub Ff. Aby uzyskać więcej informacji, zobacz Ciągi formatu wyliczenia.

W poniższym przykładzie użyto każdego z obsługiwanych ciągów formatu wyliczenia, aby przekonwertować każdą wartość wyliczenia TaskState na jego reprezentacje ciągów.

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

Metoda GetEnumName() odbicia zwraca nazwę określonej wartości wyliczenia. Wartość wejściowa musi być prawidłowym typem bazowym dla wyliczenia, takiego jak liczba całkowita lub wartość wyliczenia. Jeśli istnieje wiele nazw skojarzonych z wartością, metoda zwraca pierwszą zdefiniowaną nazwę.

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

Metoda GetEnumNames() odbicia zwraca nazwy dla każdej wartości wyliczenia jako ciągi. Dane wyjściowe zawierają synonimy.

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

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

GetEnumUnderlyingType

Metoda GetEnumUnderlyingType() odbicia zwraca podstawowy typ wartości wyliczenia.

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

Metoda GetEnumValues() odbicia zwraca każdą zdefiniowaną wartość dla wyliczenia.

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

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

GetEnumValuesAsUnderlyingType

Metoda GetEnumValuesAsUnderlyingType() odbicia zwraca każdą zdefiniowaną wartość wyliczenia jako typ bazowy.

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

Metoda HasFlag wystąpienia określa, czy flaga bitowa jest ustawiona dla wartości wyliczenia flagi. Użycie tej metody jest krótsze i łatwiejsze do odczytania niż przeprowadzenie porównania binarnego i sprawdzenia równoważności.

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

W poniższym przykładzie zdefiniowano wyliczenie flagi ModuleFeatures i pokazano, które flagi mają wartość 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

Metoda statyczna IsDefined() zwraca $true wartość, jeśli wartość wejściowa jest zdefiniowana dla wyliczenia i w przeciwnym razie $false. Użyj tej metody, aby sprawdzić, czy wartość jest prawidłowa dla wyliczenia bez konieczności obsługi nieprawidłowych błędów argumentów.

Można użyć metody statycznej w typie klasy bazowej System.Enum lub określonym typie wyliczenia.

[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

Metoda ToString() wystąpienia zwraca etykietę dla wartości wyliczenia. Ta metoda jest również widokiem domyślnym sposobu wyświetlania wartości wyliczenia jako danych wyjściowych. Opcjonalnie możesz określić ciąg formatu, aby kontrolować sposób wyświetlania wartości. Aby uzyskać więcej informacji na temat formatowania, zobacz Formatowanie wartości wyliczenia.

Uwaga

W przypadku wyliczeń definiujących synonimy dla określonej wartości nie należy pisać kodu zależnego od danych wyjściowych elementu ToString(). Metoda może zwrócić dowolną prawidłową nazwę dla wartości.

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

W poniższym przykładzie zdefiniowano wyliczenie Shade jako Gray synonim dla elementu Grey. Następnie zwraca obiekty, które pokazują rzeczywistą wartość wyliczenia, wyliczenie jako ciąg i wyliczenie jako liczbę całkowitą.

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

Synonimy wartości wyliczenia

Można zdefiniować wyliczenia, które dają różne nazwy tej samej wartości całkowitej. Gdy to zrobisz, nazwy wskazujące tę samą wartość bazowa są nazywane synonimami. Wyliczenia z synonimami umożliwiają użytkownikom określanie różnych nazw dla tej samej wartości.

Podczas definiowania wyliczenia z synonimami nie należy pisać kodu, który zależy od wartości synonimu konwertowanej na określoną nazwę. Można niezawodnie napisać kod, który konwertuje ciąg synonimu na wartość wyliczenia. Podczas pracy z samą wartością wyliczenia należy zawsze porównać ją jako wartość wyliczenia lub jego typ bazowy zamiast jako ciąg.

Poniższy blok kodu definiuje wyliczenie Shade z elementami Grey i Gray jako synonimy.

enum Shade {
    White
    Grey
    Gray = 1
    Black
}

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

Wyliczenia jako flagi

Jednym z typowych zastosowań wyliczenia jest reprezentowanie zestawu wzajemnie wykluczających się wartości. Na przykład wystąpienie ArrivalStatus może mieć wartość Early, OnTime lub Late. Nie ma sensu, aby wartość wystąpienia ArrivalStatus odzwierciedlała więcej niż jedną stałą wyliczenia.

W innych przypadkach jednak wartość obiektu wyliczenia może zawierać wiele elementów członkowskich wyliczenia, a każdy element członkowski reprezentuje pole bitowe w wartości wyliczenia. Możesz użyć atrybutu FlagsAttribute , aby wskazać, że wyliczenie składa się z pól bitowych jako flag, które użytkownicy mogą łączyć.

Aby wyliczenia jako flagi działały prawidłowo, należy ustawić wartość całkowitą każdej etykiety na moc dwóch. Jeśli nie określisz wartości etykiety, program PowerShell ustawi wartość na wyższą niż poprzednia etykieta.

Można zdefiniować wartości dla często używanych kombinacji flag, aby ułatwić użytkownikom określenie zestawu flag jednocześnie. Nazwa wartości powinna być połączonymi nazwami flag. Wartość całkowita powinna być sumą wartości flagi.

Aby określić, czy określona flaga jest ustawiona dla wartości, użyj HasFlag() metody w wartości lub użyj operatora -bandporównania binarnego .

Aby zapoznać się z przykładem pokazującym, jak używać wyliczenia flagi i sprawdzić, czy flaga jest ustawiona, zobacz Przykład 3.

Wyliczenia jako parametry

Możesz zdefiniować parametry polecenia cmdlet, które używają wyliczenia jako ich typu. Po określeniu wyliczenia jako typu parametru użytkownicy uzyskują automatyczne uzupełnianie i walidację wartości parametru. Uzupełnianie argumentu sugeruje listę prawidłowych etykiet dla wyliczenia.

Jeśli parametr ma wyliczenie jako jego typ, można określić dowolny z:

  • Wyliczenie, na przykład [<EnumType>]::<Label>
  • Etykieta wyliczenia jako ciąg
  • Wartość liczbowa wyliczenia

Aby zapoznać się z przykładem pokazującym zachowanie parametru typu wyliczenia, zobacz Przykład 4.

Wyliczenia z określonymi typami bazowymi

Począwszy od programu PowerShell 6.2, można zdefiniować wyliczenia z określonym typem bazowym. Podczas definiowania wyliczenia bez określonego typu bazowego program PowerShell tworzy wyliczenie ([int]System.Int32) jako typ bazowy.

Podstawowym typem wyliczenia musi być całkowity typ liczbowy. Poniższa lista zawiera prawidłowe typy z krótką nazwą i pełną nazwą typu:

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

Można zdefiniować określony typ bazowy dla wyliczenia jako krótką nazwę lub pełną nazwę typu. Poniższe definicje są funkcjonalnie identyczne. Tylko nazwa używana dla typu bazowego jest inna.

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

Formatowanie wartości wyliczenia

Wartości wyliczenia można przekonwertować na ich reprezentacje ciągów, wywołując metodę static Format, a także przeciążenia metody ToString wystąpienia. Możesz użyć ciągu formatu, aby kontrolować dokładny sposób, w jaki wartość wyliczenia jest reprezentowana jako ciąg. Aby uzyskać więcej informacji, zobacz Ciągi formatu wyliczenia.

W poniższym przykładzie użyto każdego z obsługiwanych ciągów formatu wyliczenia (G lub Dg, lub Xdlub x) Ff w celu przekonwertowania każdego elementu członkowskiego wyliczenia TaskState na jego reprezentacje ciągów.

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

W poniższym przykładzie użyto ciągów formatu dla wartości wyliczenia flagi.

[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

Zwróć uwagę, GF że w przypadku wyliczenia flag i ciągi formatu wyświetlają listę flag zestawu dla wartości rozdzielonych przecinkami. Ostatnia wartość , nie wyświetla żadnych flag, 8ponieważ w rzeczywistości nie jest to prawidłowy zestaw flag. Nie można połączyć flag wyliczenia, aby uzyskać sumę 8 bez duplikowania co najmniej jednej flagi.

Definiowanie metod rozszerzeń za pomocą metody Update-TypeData

Nie można zdefiniować metod w deklaracji dla wyliczenia. Aby rozszerzyć funkcjonalność wyliczenia, możesz użyć polecenia cmdlet Update-TypeData , aby zdefiniować ScriptMethod elementy członkowskie dla wyliczenia.

W poniższym przykładzie użyto Update-TypeData polecenia cmdlet , aby dodać metodę GetFlags() do wyliczenia flagi FileAttributes . Zwraca tablicę flag ustawionych dla wartości.

[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

Eksportowanie wyliczenia z akceleratorami typów

Domyślnie moduły programu PowerShell nie eksportują automatycznie klas i wyliczeń zdefiniowanych w programie PowerShell. Typy niestandardowe nie są dostępne poza modułem bez wywoływania instrukcji using module .

Jeśli jednak moduł dodaje akceleratory typów, akceleratory tego typu są natychmiast dostępne w sesji po zaimportowaniu modułu przez użytkowników.

Uwaga

Dodawanie akceleratorów typów do sesji używa wewnętrznego (nie publicznego) interfejsu API. Użycie tego interfejsu API może powodować konflikty. Wzorzec opisany poniżej zgłasza błąd, jeśli akcelerator typu o tej samej nazwie już istnieje podczas importowania modułu. Usuwa również akceleratory typów podczas usuwania modułu z sesji.

Ten wzorzec gwarantuje, że typy są dostępne w sesji. Nie ma to wpływu na funkcję IntelliSense ani uzupełnianie podczas tworzenia pliku skryptu w programie VS Code. Aby uzyskać sugestie dotyczące funkcji IntelliSense i uzupełniania dla typów niestandardowych w programie VS Code, należy dodać instrukcję using module na początku skryptu.

Poniższy wzorzec pokazuje, jak zarejestrować klasy programu PowerShell i wyliczenia jako akceleratory typów w module. Dodaj fragment kodu do modułu skryptu głównego po dowolnych definicjach typów. Upewnij się, że zmienna $ExportableTypes zawiera każdy z typów, które mają być dostępne dla użytkowników podczas importowania modułu. Drugi kod nie wymaga edycji.

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

Podczas importowania modułu przez użytkowników wszystkie typy dodane do akceleratorów typów dla sesji są natychmiast dostępne dla funkcji IntelliSense i uzupełniania. Po usunięciu modułu są więc akceleratory typów.

Ręczne importowanie wyliczeń z modułu programu PowerShell

Import-Module i instrukcja #requires importuje tylko funkcje modułu, aliasy i zmienne, zgodnie z definicją w module. Wyliczenia nie są importowane.

Jeśli moduł definiuje klasy i wyliczenia, ale nie dodaje akceleratorów typów dla tych typów, użyj using module instrukcji , aby je zaimportować.

Instrukcja using module importuje klasy i wyliczenia z modułu głównego (ModuleToProcess) modułu skryptu lub modułu binarnego. Nie importuje spójnie klas zdefiniowanych w zagnieżdżonych modułach ani klasach zdefiniowanych w skryptach, które są dot-source do modułu głównego. Zdefiniuj klasy, które mają być dostępne dla użytkowników spoza modułu bezpośrednio w module głównym.

Aby uzyskać więcej informacji na temat instrukcji using , zobacz about_Using.

Ładowanie nowo zmienionego kodu podczas programowania

Podczas opracowywania modułu skryptu często wprowadza się zmiany w kodzie, a następnie ładują nową wersję modułu przy użyciu Import-Module parametru Force . Działa to tylko w przypadku zmian funkcji w module głównym. Import-Module nie ładuje ponownie żadnych zagnieżdżonych modułów. Ponadto nie ma możliwości załadowania zaktualizowanych klas.

Aby upewnić się, że używasz najnowszej wersji, musisz uruchomić nową sesję. Nie można zwolnić klas i wyliczenia zdefiniowanych w programie PowerShell i zaimportowanych za pomocą using instrukcji.

Innym typowym rozwiązaniem programistycznym jest rozdzielenie kodu na różne pliki. Jeśli masz funkcję w jednym pliku, który używa wyliczeń zdefiniowanych w innym module, należy użyć using module instrukcji , aby upewnić się, że funkcje mają wymagane definicje wyliczenia.

Ograniczenia

  • Nie można dekorować wartości wyliczenia zdefiniowanych w programie PowerShell za pomocą atrybutów. Możesz udekorować tylko samą deklarację wyliczenia, tak jak w przypadku atrybutu FlagsAttribute do definiowania wyliczenia jako zestawu flag bitowych.

    Obejście: brak

  • Nie można definiować metod wewnątrz definicji wyliczenia, a program PowerShell nie obsługuje definiowania [metod rozszerzeń], takich jak C#.

    Obejście: Użyj polecenia cmdlet Update-TypeData , aby zdefiniować ScriptMethod elementy członkowskie dla wyliczenia.