The example below is simply for illustration. I'm not looking for optimization or any sort of workaround solutions as this function obviosuly doesn't do anything useful - again, it's simply for presenting:
- Accepting an entire enum type/structure as an argument
- Doing something (anything) with the passed enum argument/param.
- In this case it simply retrieves the enum name that corresponds to the int value of 2.
The following works to accept a single enum type as an argument and outputs the expected value:
function EnumTest
{
param ([System.Object]$EnumObject)
BEGIN {}
PROCESS
{
[System.Enum]::GetName($EnumObject, 2)
}
END {}
}
enum MyCustomEnum
{
Balloon = 1
Bicycle = 2
Cloud = 3
}
enum MyOtherCustomEnum
{
Crayon = 1
Dog = 2
Elephant = 3
}
EnumTest -EnumObject MyCustomEnum
Output:
Bicycle
Questions:
How can I get the param $EnumObject to accept an array of enum types (the entire enum structure, not just one of its names/values), e.g.:
EnumTest -EnumObject MyCustomEnum, MyOtherCustomEnum
[System.Object[]]$EnumObject
doesn't work[System.Enum[]]$EnumObject
doesn't work- Why doesn't this work?
[array]$EnumObject
doesn't work
What is the appropriate way to pass an entire enum type as an argument?
EnumTest -EnumObject MyCustomEnum
appears to pass the enum structure's name "MyCustomEnum" as a string instead of the intended (entire) enum object[MyCustomEnum]
.
CodePudding user response:
PowerShell interprets the bare word token MyCustomEnum
in this statement:
EnumTest -EnumObject MyCustomEnum
... as a string literal, no different than if you'd done:
EnumTest -EnumObject "MyCustomEnum"
If you just want to pass the type as a parameter argument, place a type literal in a subexpression like this:
EnumTest -EnumObject $([MyCustomEnum])
[object]
/[System.Object]
as parameter type will work here, since every type ultimately inherits from [object]
anyway.
If you want to restrict parameter arguments to only types, use [type]
as the parameter type:
function EnumTest
{
param (
[type]$EnumType
)
process {
if($EnumType.IsEnum){
[System.Enum]::GetName($EnumObject, 2)
}
}
}
If you want to pass an arbitrary number of enums either as positional arguments or via the pipeline, add an appropriate [Parameter()]
attribute and (for trailing argument support) change the parameter type to an array of [type]
:
function EnumTest
{
param (
[Parameter(ValueFromPipeline, ValueFromRemainingArguments)]
[type[]]$EnumType
)
process {
foreach($type in $EnumType){
if($type.IsEnum){
[System.Enum]::GetName($type, 2)
}
}
}
}
Now all of the below invocation scenarios will work:
EnumTest $([MyCustomEnum]) $([MyOtherCustomEnum])
# or
EnumTest @([MyCustomEnum], [MyOtherCustomEnum])
# or
[MyCustomEnum],[MyOtherCustomEnum] |EnumTest
# or
$enumTypes = [MyCustomEnum],[MyOtherCustomEnum]
EnumTest -EnumType $enumTypes
# or, if you wanna get funky:
$paramArgs = @{ EnumType = 'MyCustomEnum,MyOtherCustomEnum' -split ',' -as [type[]] }
EnumTest @paramArgs
A previous version of the question made it sound like the user wanted to store multiple enum values as a scalar value, hence this answer:
It looks like you'll want to decorate the enum type with the Flags
attribute - this will allow you to store compound values:
[Flags()]
enum MyCustomEnum
{
FirstName = 1
SecondName = 2
ThirdName = 4
}
Now multiple flags can be stored in a single instance of MyCustomEnum
:
PS ~> $value = [MyCustomEnum]'FirstName, ThirdName'
PS ~> $value.value__ # the instance now stores the value of `FirstName -bor ThirdName`
5
The presence or absence of each individually defined value can be interrogated with the Enum.HasFlag
method:
PS ~> $value = [MyCustomEnum]'FirstName, ThirdName'
PS ~> $value.HasFlag('FirstName')
True
PS ~> $value.HasFlag('SecondName')
False