about_Enum
Краткое описание
Оператор enum
объявляет перечисление . Перечисление — это отдельный тип, состоящий из набора именованных меток, называемых списком перечислителя.
Подробное описание
Оператор enum
позволяет создать строго типизированный набор меток. Это перечисление можно использовать в коде без анализа или проверка для орфографических ошибок.
Перечисления внутренне представлены как целочисленные типы значений с начальным значением 0. По умолчанию перечисления PowerShell используют System.Int32 ([int]
) в качестве базового типа. По умолчанию PowerShell назначает первой метке в списке нулевое значение. По умолчанию PowerShell назначает оставшиеся метки с последовательными целыми числами.
В определении можно присвоить меткам любое целочисленное значение. Метки без присвоенного значения принимают следующее целочисленное значение.
Синтаксис
Перечисления используют следующий синтаксис:
Синтаксис определения перечисления integer
[[<attribute>]...] enum <enum-name> {
<label> [= <int-value>]
...
}
Синтаксис определения перечисления конкретных базовых типов
[[<attribute>]...] enum <enum-name> : <underlying-type-name> {
<label> [= <int-value>]
...
}
Синтаксис определения перечисления флагов
[[<attribute>]...] [Flag()] enum <enum-name>[ : <underlying-type-name>] {
<label 0> [= 1]
<label 1> [= 2]
<label 2> [= 4]
<label 3> [= 8]
...
...
}
Синтаксис доступа к перечислению
[<enum-name>]::<label>
Примеры
Пример 1. Минимальное перечисление
Следующий блок кода определяет перечисление MarkdownUnorderedListCharacter с тремя метками. Он не присваивает явные значения какой-либо метки.
enum MarkdownUnorderedListCharacter {
Asterisk
Dash
Plus
}
В следующем блоке кода показано поведение целочисленных и строковых значений при приведении к типу перечисления.
$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
Приведение целых чисел, равных значению перечисления, возвращает это перечисление. Приведение строк, которые совпадают с меткой перечисления, возвращает это перечисление.
Пример 2. Значения явного перечисления и перечисления синонимов
В следующем примере показано перечисление объектов, коррелирующих с файлами мультимедиа. Определение присваивает явные значения базовым значениям music
, picture
, video
. Метки сразу после явного назначения получают следующее целочисленное значение. Синонимы можно создать, назначив то же значение другой метки; см. сконструированные значения для : ogg
, oga
, mogg
или jpg
, jpeg
или 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
}
Метод GetEnumNames()
возвращает список меток для перечисления .
[MediaTypes].GetEnumNames()
unknown
music
mp3
aac
ogg
oga
mogg
picture
jpg
jpeg
png
video
mpg
mpeg
avi
m4v
Метод GetEnumValues()
возвращает список значений для перечисления .
[MediaTypes].GetEnumValues()
unknown
music
mp3
aac
ogg
ogg
ogg
picture
jpg
jpg
png
video
mpg
mpg
avi
m4v
Примечание
GetEnumNames()
и GetEnumValues()
возвращают те же результаты; список именованных значений. Однако внутренне перечисляет значения, GetEnumValues()
а затем сопоставляет значения с именами. Внимательно прочтите список, и вы заметите, что ogg
, oga
и mogg
отображаются в выходных GetEnumNames()
данных , но в выходных GetEnumValues()
данных отображается ogg
только . То же самое происходит для jpg
, jpeg
и mpg
. mpeg
Имя, возвращаемое PowerShell для значений синонимов, не является детерминированным.
Метод можно использовать для GetEnumName()
получения имени, связанного с определенным значением. Если со значением связано несколько имен, метод возвращает первое определенное имя.
[MediaTypes].GetEnumName(15)
ogg
В следующем примере показано, как сопоставить каждое имя со значением.
[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
Одно значение перечисления можно указать с помощью его метки с помощью синтаксиса [<enum-name>]::<label>
.
[MediaTypes]::png
[MediaTypes]::png -eq 22
png
True
Пример 3. Перечисление в виде флагов
Следующий блок кода создает перечисление FileAttributes в виде набора битовых флагов. Значение каждой метки в два раза превышает значение предыдущей метки.
[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
Чтобы проверить, установлен ли определенный флаг, можно использовать бинарный оператор -band
сравнения . В этом примере проверяется наличие атрибутов Device и Archive в значении $file2
.
PS > ($file2 -band [FileAttributes]::Device) -eq [FileAttributes]::Device
True
PS > ($file2 -band [FileAttributes]::Archive) -eq [FileAttributes]::Archive
False
Вы также можете использовать метод , HasFlag()
чтобы проверить, установлен ли определенный флаг.
В этом примере выполняется проверка атрибутов Device и Hidden в значении $file1
.
PS > $file1.HasFlag([FileAttributes]::Device)
True
PS > $file1.HasFlag([FileAttributes]::Hidden)
False
Пример 4. Перечисление в качестве параметра
В следующем примере функция ConvertTo-LineEndingRegex
определяет параметр InputObject с типом 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
В этом примере первый оператор, вызывающий ConvertTo-LineEndingRegex
, передает значение перечисления для CR
. Второй оператор передает строку 'CRLF'
, которая приводится к LineEnding. Третий оператор задает значение 2
параметра , которое сопоставляется с меткой LF
.
Параметры завершения аргументов можно просмотреть, введя следующий текст в командной строке PowerShell:
ConvertTo-LineEndingRegex -InputObject <Tab>
При указании недопустимого имени метки или числового значения для параметра функция выдает ошибку.
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".
Пример 5. Перечисления с определенными базовыми типами
Начиная с PowerShell 6.2, можно определить перечисления с определенным базовым типом. В этом примере показаны допустимые базовые типы для перечисления.
Первый блок кода инициализирует две переменные как массивы. $EnumTypes
— это пустой массив для хранения динамически создаваемых типов. $IntegralTypes
— это массив, содержащий допустимые базовые типы для перечисления.
$EnumTypes = @()
$IntegralTypes = @(
'byte', 'sbyte', 'short', 'ushort', 'int', 'uint', 'long', 'ulong'
)
Следующий блок кода определяет шаблон для динамического создания определений перечисления. {0}
Если заполнитель формата заменяется именем целочисленного типа, шаблон создает блок скрипта, который:
Определяет перечисление с именем
<type>Enum
, напримерbyteEnum
. Определенное перечисление использует указанный целочисленный тип в качестве базового типа значения.Перечисление определяется со значением
Min
, равным минимальному значению целочисленного типа. Он определяет максимальноеMax
значение для целочисленного типа.Возвращает только что определенный тип.
$DefinitionTemplate = @"
enum {0}Enum : {0} {{
Min = [{0}]::MinValue
Max = [{0}]::MaxValue
}}
[{0}Enum]
"@
Следующий блок кода использует шаблон для создания и вызова scriptblock в текущем область. Он добавляет возвращенные определения типов в $EnumTypes
массив.
foreach ($IntegralType in $IntegralTypes) {
$Definition = $DefinitionTemplate -f $IntegralType
$ScriptBlock = [scriptblock]::Create($Definition)
$EnumTypes += . $ScriptBlock
}
Последний блок кода выполняет цикл над типами перечисления, используя GetEnumValuesAsUnderlyingType()
метод для перечисления значений в качестве базового типа. Цикл создает новый объект для каждого значения, отображая тип перечисления, тип значения, метку и фактическое значение.
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
Методы перечисления
В следующем списке приведены полезные методы, доступные для перечислений в PowerShell, и способы их использования.
Формат
Статический Format()
метод возвращает форматированные строковые выходные данные для заданного типа перечисления, значения перечисления и строки форматирования. Выходные данные совпадают с вызовом метода ToString для значения с указанной строкой формата.
Статический метод можно использовать для базового типа класса System.Enum или определенного типа перечисления.
[System.Enum]::format([<enum-name>], <value>, <format-string>)
[<enum-name>]::format([<enum-name>], <value>, <format-string>)
Допустимые строки формата: G
или g
, D
или d
, X
и x
F
или f
. Дополнительные сведения см. в разделе Строки формата перечисления.
В следующем примере каждая из поддерживаемых строк формата перечисления используется для преобразования каждого значения перечисления TaskState в его строковые представления.
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
Метод GetEnumName()
отражения возвращает имя для определенного значения перечисления. Входное значение должно быть допустимым базовым типом перечисления, например целое число или значение перечисления. Если со значением связано несколько имен, метод возвращает первое определенное имя.
[<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
Метод GetEnumNames()
отражения возвращает имена для каждого значения перечисления в виде строк. Выходные данные включают синонимы.
[<enum-name>].GetEnumNames()
enum Season {
Unknown
Spring
Summer
Autumn
Winter
Fall = 3
}
[Season].GetEnumNames()
Unknown
Spring
Summer
Fall
Autumn
Winter
GetEnumUnderlyingType
Метод GetEnumUnderlyingType()
отражения возвращает базовый тип для значений перечисления.
[<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
Метод GetEnumValues()
отражения возвращает каждое определенное значение для перечисления.
[<enum-name>].GetEnumValues()
enum Season {
Unknown
Spring
Summer
Autumn
Winter
Fall = 3
}
[Season].GetEnumValues()
Unknown
Spring
Summer
Fall
Fall
Winter
GetEnumValuesAsUnderlyingType
Метод GetEnumValuesAsUnderlyingType()
отражения возвращает каждое определенное значение для перечисления в качестве базового типа.
[<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
Метод HasFlag
экземпляра определяет, установлен ли битовый флаг для значения перечисления флагов. Использование этого метода короче и проще для чтения, чем двоичное сравнение и эквивалентность проверка.
<enum-value>.HasFlag(<enum-flag-value>)
В следующем примере определяется перечисление флагов ModuleFeatures и показано, какие флаги имеет значение 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
Статический IsDefined()
метод возвращает значение $true
, если входное значение определено для перечисления и в противном случае $false
. Используйте этот метод, чтобы проверка, является ли значение допустимым для перечисления без обработки ошибок недопустимых аргументов.
Статический метод можно использовать для базового типа класса System.Enum или определенного типа перечисления.
[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
Метод ToString()
экземпляра возвращает метку для значения перечисления.
Этот метод также является представлением по умолчанию для отображения значения перечисления в качестве выходных данных. При необходимости можно указать строку формата для управления отображением значения. Дополнительные сведения о форматировании см. в разделе Форматирование значений перечисления.
Примечание
Для перечислений, определяющих синонимы для определенного значения, не создавайте код, зависящий от выходных ToString()
данных . Метод может возвращать любое допустимое имя для значения.
<enum-value>.ToString([<format-string>])
В следующем примере перечисление Shade определяется с Gray
в качестве синонима для Grey
. Затем он выводит объекты, которые показывают фактическое значение перечисления, перечисление в виде строки и перечисление в виде целого числа.
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
Синонимы значений перечисления
Можно определить перечисления, которые присваивают разные имена одному и тому же целочисленному значению. При этом имена, указывающие на одно и то же базовое значение, называются синонимами. Перечисления с синонимами позволяют пользователям указывать разные имена для одного и того же значения.
При определении перечисления с синонимами не следует писать код, зависящий от значения синонима, преобразующегося в определенное имя. Вы можете надежно написать код, который преобразует строку синонима в значение перечисления. При работе со значением перечисления всегда сравнивайте его как значение перечисления или его базовый тип, а не как строку.
В следующем блоке кода перечисление Shade определяется с Grey
помощью и Gray
в качестве синонимов.
enum Shade {
White
Grey
Gray = 1
Black
}
[Shade]'Grey' -eq [Shade]::Gray
[Shade]::Grey -eq 1
[Shade]'Gray' -eq 1
True
True
True
Перечисления как флаги
Одним из распространенных способов использования перечисления является представление набора взаимоисключающих значений. Например, экземпляр ArrivalStatus может иметь значение Early, OnTime или Late. Значение экземпляра ArrivalStatus не имеет смысла отражать несколько констант перечисления.
Однако в других случаях значение объекта перечисления может включать несколько элементов перечисления, и каждый элемент представляет битовое поле в значении перечисления. С помощью flagsAttribute можно указать, что перечисление состоит из битовых полей в качестве флагов, которые пользователи могут объединять.
Чтобы перечисления в качестве флагов работали правильно, необходимо задать для каждой метки целочисленное значение, равное двум. Если не указать значение для метки, PowerShell установит значение на один выше предыдущей метки.
Вы можете определить значения для часто используемых сочетаний флагов, чтобы пользователям было проще одновременно указать набор флагов. Имя значения должно быть объединенным именам флагов. Целочисленное значение должно быть суммой значений флагов.
Чтобы определить, задан ли определенный флаг для значения, используйте HasFlag()
метод для значения или бинарный оператор -band
сравнения .
Пример использования перечислений флагов и проверка, установлен ли флаг, см. в примере 3.
Перечисления в качестве параметров
Можно определить параметры командлета, использующие перечисление в качестве типа. При указании перечисления в качестве типа параметра пользователи получают автоматическое завершение и проверку значения параметра. Завершение аргумента предлагает список допустимых меток для перечисления.
Если параметр имеет в качестве типа перечисление, можно указать любой из:
- Перечисление, например
[<EnumType>]::<Label>
- Метка для перечисления в виде строки
- Числовое значение перечисления
Пример, показывающий поведение параметра, типизированного перечислением, см. в примере 4.
Перечисления с определенными базовыми типами
Начиная с PowerShell 6.2, можно определить перечисления с определенным базовым типом. При определении перечисления без определенного базового типа PowerShell создает перечисление с [int]
(System.Int32) в качестве базового типа.
Базовым типом перечисления должен быть целочисленный тип. В следующем списке указаны допустимые типы с коротким именем и полным именем типа:
byte
- System.Bytesbyte
- System.SByteshort
- System.Int16ushort
- System.UInt16int
- System.Int32uint
- System.UInt32long
- System.Int64ulong
- System.UInt64
Вы можете определить конкретный базовый тип для перечисления как короткое или полное имя типа. Следующие определения функционально идентичны. Отличается только имя, используемое для базового типа.
enum LongValueEnum : long {
Zero
One
Two
}
enum LongValueEnum : System.Int64 {
Zero
One
Two
}
Форматирование значений перечисления
Значения перечисления можно преобразовать в их строковые представления, вызвав статический метод Format , а также перегрузки экземпляра метода ToString . Строку формата можно использовать для управления точным способом представления значения перечисления в виде строки. Дополнительные сведения см. в разделе Строки формата перечисления.
В следующем примере используется каждая из поддерживаемых строк формата перечисления (G
или g
, D
или d
, X
или x
, и F
или f
) для преобразования каждого элемента перечисления TaskState в его строковые представления.
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
В следующем примере строки формата используются для значений перечисления флагов.
[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
Обратите внимание, что для перечислений флагов строки формата и F
отображают список установленных флагов для значения, G
разделенного запятыми. Последнее значение, , не содержит никаких флагов, 8
так как на самом деле оно не является допустимым набором флагов. Невозможно объединить флаги перечисления для получения суммы без дублирования хотя бы одного флага 8
.
Определение методов расширения с помощью Update-TypeData
Вы не можете определить методы в объявлении для перечисления. Чтобы расширить функциональность перечисления, можно использовать командлет Update-TypeData для определения ScriptMethod
элементов перечисления.
В следующем примере командлет используется Update-TypeData
для добавления GetFlags()
метода в перечисление флага FileAttributes . Он возвращает массив флагов, установленных для значения .
[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
Экспорт перечислений с помощью ускорителей типов
По умолчанию модули PowerShell не экспортируют автоматически классы и перечисления, определенные в PowerShell. Пользовательские типы недоступны за пределами модуля без вызова using module
оператора .
Однако если модуль добавляет ускорители типов, эти ускорители сразу же становятся доступны в сеансе после импорта модуля пользователями.
Примечание
При добавлении ускорителей типов в сеанс используется внутренний (не открытый) API. Использование этого API может привести к конфликтам. Описанный ниже шаблон выдает ошибку, если при импорте модуля уже существует ускоритель типов с тем же именем. Он также удаляет ускорители типов при удалении модуля из сеанса.
Этот шаблон гарантирует, что типы будут доступны в сеансе. Это не влияет на IntelliSense или завершение при создании файла скрипта в VS Code.
Чтобы получить предложения IntelliSense и завершения для пользовательских типов в VS Code, необходимо добавить using module
оператор в начало скрипта.
В следующем шаблоне показано, как зарегистрировать классы и перечисления PowerShell в качестве ускорителей типов в модуле. Добавьте фрагмент кода в модуль корневого скрипта после любых определений типов. Убедитесь, $ExportableTypes
что переменная содержит все типы, которые вы хотите сделать доступными для пользователей при импорте модуля. Другой код не требует редактирования.
# 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()
Когда пользователи импортируют модуль, все типы, добавленные в ускорители типов для сеанса, сразу же становятся доступными для IntelliSense и завершения. При удалении модуля также удаляются ускорители типов.
Импорт перечислений вручную из модуля PowerShell
Import-Module
#requires
и инструкция импортирует только функции модуля, псевдонимы и переменные, как определено в модуле. Перечисления не импортируются.
Если модуль определяет классы и перечисления, но не добавляет ускорители типов для этих типов, используйте using module
оператор для их импорта.
Инструкция using module
импортирует классы и перечисления из корневого модуля (ModuleToProcess
) модуля скрипта или двоичного модуля. Он не последовательно импортирует классы, определенные во вложенных модулях, или классы, определенные в скриптах, которые находятся в корневом модуле. Определите классы, которые должны быть доступны пользователям за пределами модуля, непосредственно в корневом модуле.
Дополнительные сведения об инструкции см. в using
разделе about_Using.
Загрузка нового измененного кода во время разработки
Во время разработки модуля скрипта обычно вносятся изменения в код, а затем загружают новую версию модуля с помощью Import-Module
параметра Force . Это работает только для изменений функций в корневом модуле. Import-Module
не перезагружает вложенные модули. Кроме того, нет способа загрузить обновленные классы.
Чтобы убедиться, что используется последняя версия, необходимо запустить новый сеанс.
Классы и перечисления, определенные в PowerShell и импортированные с помощью инструкции using
, не могут быть выгружены.
Другой распространенной методикой разработки является разделение кода на разные файлы. Если в одном файле есть функция, которая использует перечисления, определенные в другом модуле, следует использовать инструкцию using module
, чтобы убедиться, что функции имеют необходимые определения перечисления.
Ограничения
Значения перечисления, определенные в PowerShell, нельзя украсить атрибутами. Вы можете украсить только само объявление перечисления, как с FlagsAttribute для определения перечисления как набора битовых флагов.
Обходной путь: нет
Вы не можете определить методы в определениях перечисления, и PowerShell не поддерживает определение [методов расширения], таких как C#.
Обходной путь. Используйте командлет Update-TypeData , чтобы определить
ScriptMethod
элементы для перечисления.