When using an enum in PowerShell, use the member’s name, not the member’s value

Consider the following enum in C#:

enum State
{
    Started,
    Stopped,
    Unknown
}

Note that I have not added an explicit value for the enum members. They will be generated by the compiler. As stated in the C# spec:

… its associated value is set implicitly, as follows:

  • If the enum member is the first enum member declared in the enum type, its associated value is zero.
  • Otherwise, the associated value of the enum member is obtained by increasing the associated value of the textually preceding enum member by one. This increased value must be within the range of values that can be represented by the underlying type, otherwise a compile-time error occurs.

Found at http://www.microsoft.com/en-us/download/details.aspx?id=7029, page 400-401 (I can’t find the version for 4.5 though…).

Now what are the consequences of this? Consider the following piece of PowerShell:

$result = $serviceController.GetServiceStatus()
if($result -eq 1)
{
    MyLib.StartService()
}

This will work, because PowerShell implicitly converts the int to the actual enum member.

However since we are assuming the value can go wrong. In the next version you add extra values, say for example to represent a starting/stopping service:

enum State
{
    Starting,
    Started,
    Stopping,
    Stopped,
    Unknown
}

Since now all the values are shifted when you run your PowerShell again you start the service when it’s already started 😉 .

Solution?

First of all (as a consumer), use the enum’s member name instead of its value:

$result = $serviceController.GetServiceStatus()
if($result -eq [MyLib.State]::Stopped)
{
    MyLib.StartService()
}

This will ensure that you get the value for Started, not for anything else.

As a developer of a library you should ensure that you never mess up the order of an enum, by adding new values as last, or (prefered) set the value yourself:

enum State
{
    Started = 0,
    Stopped = 1,
    Unknown = 2,
}

Becomes:

enum State
{
    Starting = 3,
    Started = 0,
    Stopping = 4,
    Stopped = 1,
    Unknown = 2,
}

And now you can also perfectly reorder them so the numbers are sequential:

enum State
{
    Started = 0,
    Stopped = 1,
    Unknown = 2,
    Starting = 3,
    Stopping = 4,
}

Hope you have a good one,

-Kristof

One thought on “When using an enum in PowerShell, use the member’s name, not the member’s value”

  1. I’m having a problem where I do the equivalent of your [MyLib.State]::Stopped, and I get an error:
    Unable to find type [MyLib.State]. Make sure that the assembly that contains this type is loaded.

    But I am loading the assemble and I am successfully using other objects in that assemble, so why can’t I use the enum? I have powershell 4, maybe Microsoft removed support for enums? Is there a different syntax? Perhaps you can share your entire script so I can analyze it and determine how min e is different?

Comments are closed.