Monday, November 03, 2014

Enums in PowerShell V5

As I noted in an earlier blog post, we have begun to see the contents of what eventually is to become PowerShell V5. Amongst the cool features that are to be delivered in V5, one of my favourite is the ability to define Classes and Enums in PowerShell. I'll leave Classes for another day (and possibly multiple blog posts), but let's look at Enums.

First, what is an enum? An enum is a type that create a list of named constants. In the .NET Framework, you find the System.Enum class – which implements enums.

You can think of an enum as all the proper values that some parameter can take. For example, if you were implementing a pizza application, you might have an enum called PizzaSize, representing the available sizes of pizza and another enum called PizzaToppings that contains the valid names of all the toppings you can put on your pizza.

Of course, you could have always used the ENUM feature of .NET, and there are a lot of enums already defined.  For example, System.Net.Mail.MailPriority is an existing enum in the .NET Framework 4.5, which specifies the valid values for mail priority. This is a simple enum, with just three values: High, Low and Normal. If your code/script/function is passed a value for mail priority, it's always a good idea to validate it – and here's some PowerShell Code that can do this:

# Enums.ps1
Function Confirm-MailPriority {
param ([string] $mailpriority)
if ([enum]::IsDefined(([System.Net.Mail.MailPriority]),$mailpriority))
   {Return $true}
Else
   {return $false}
}

This function takes a string representing mail priority and returns true or false depending on whether it's valid. Here is the results of testing this function:

image

Now as you can see – the validation is case sensitive – thus 'High' is a valid mail priority, whereas 'high' isn't. You can get around that by fully spelling out the enum, and letting .NET work out the validity. Thus 'high' is invalid whereas [System.Net.Mail.MailPriority]::high (and [System.Net.Mail.MailPriority]::High) are both valid. This matters a lot if you are calling .Net method and passing enumerable values (e.g. mail priority). 

Up until Version 5 of PowerShell, you could always use the [enum] class to validate and list all the valid values of existing Enums. But what you did not have, up till now, is the ability to create a real Enum in PowerShell. Of course, you could have used Add-Type, and specified the C# code but I don't regard that as quite the same thing as defining an enum in PowerShell directly.

In V5, it's trivial to create an enum.  Just specify it's name, follow it by a script block with each enumerable value on a separate line. Like this:

Enum PizzaSize {
  Small
  Medium
  Regular
  Large
  ExtraLarge
}

Note there are no commas separating the values,just a newline. I wonder if this is a limitation of the current release and maybe additional delimiters will come in later versions. We'll have to see!

Once you define this enum, you can then use the enum and can validate it:

$size = [pizzasize]::large
[enum]::IsDefined(([pizzasize]),$size))  # True!

This is pretty cool – and lays at least part of the foundation for you to be able to develop full .NET Classes in PowerShell. 

There is at least one limitation I am aware of with Enums in PowerShell and that is that they are not persistent. Unlike the .NET Framework enums which are always available (one the relevant .NET Class Library is loaded!), you need to define enums in each script that uses them. That is, thinking about it, not such a great limitation – you just need to define your enums where you use them.

My preferred place is as as part of a module definition – just put your enums for your module in a file such as Enums.ps1 and put it into the module folder. Then, in the ScriptsToProcess key of the module's manifest, just specify Enums.ps1. That will dot-source them into your global environment and are then available for all the code you then run.

Enums are one important part of being able to develop a class in PowerShell. I'll be developing another article to describe how that works. I will probably wait till after the next drop of PowerShell V4, which is scheduled for November some time.

Technorati Tags: ,,,

No comments: