Quick tip: Enum with string values

Using enums can come in handy in many situations. When writing an advanced function in PowerShell, using an enum as the parameter type will ensure that only valid values are used, as well as give you tab-complete functionality (The same can be achieved using ValidateSet).

Now, I was working on extending my Mockaroo function when I found myself in a position where I needed to validate a large amount of values for a parameter. I decided on an enum, but I had problem – some of the values where strings with spaces in them, and I was going to use the parameter value when creating a URI for the Mockaroo API, so I’d rather avoid using a huge switch-statement translating the enum values to strings.

As you might know, eunums are constants and may not include spaces. If you don’t take my word for it, let’s do some experiments. Let’s start by creating a short enum:

Add-Type -TypeDefinition @"
public enum AndroidVersion
    {
        JellyBean,
        KitKat,
        Lollipop
    }
"@

Running this code works a charm, but what if we want to use spaces in the enum values? Let’s try:

Add-Type -TypeDefinition @"
public enum AndroidVersion
    {
        Jelly Bean,
        KitKat,
        Lollipop
    }
"@

enumTest01

Clearly that didn’t work. And enclosing the enum in quotation marks won’t help either. So how can we get around this? Well, I didn’t know so I started to research, and I found a solution created by Wayne Hartman in c#. He created a helper class called EnumUtils that have two methods; ‘stringValueOf’ and ‘enumValueOf’. All we have to do is to add a Description Attribute to the enums when declaring them. Let’s test it out.

Add-Type -TypeDefinition @"
    using System;
    using System.Reflection;
    using System.ComponentModel;

    public enum AndroidVersion
    {
        [DescriptionAttribute("Jelly Bean")]JellyBean,
        KitKat,
        Lollipop
    }

    public class EnumUtils
    {
        public static string stringValueOf(Enum value)
        {
            FieldInfo fi = value.GetType().GetField(value.ToString());
            DescriptionAttribute[] attributes = (DescriptionAttribute[]) fi.GetCustomAttributes( typeof(DescriptionAttribute), false);
            if (attributes.Length > 0)
            {
                return attributes[0].Description;
            }
            else
            {
                return value.ToString();
            }
        }

        public static object enumValueOf(string value, Type enumType)
        {
            string[] names = Enum.GetNames(enumType);
            foreach (string name in names)
            {
                if (stringValueOf((Enum)Enum.Parse(enumType, name)).Equals(value))
                {
                    return Enum.Parse(enumType, name);
                }
            }

            throw new ArgumentException("The string is not a description or value of the specified enum.");
        }
    }
"@

enumTest02

Great, no error messages. Let’s first try to get the enum value of JellyBean the normal way.

enumTest03

But the whole reason for doing this was to be able to get ‘Jelly Bean’ and not ‘JellyBean’, so let’s use the EnumUtils class:

enumTest04

There you have it! Jelly Bean. Cool eh? Now, back to coding…

2 comments

    1. PSv5 have made it easier to make enums, but I haven’t played with it enough to say if there is an easier way of achieving strings as in the examples here. Probably not, but if I find out, I will add an update to this post 🙂

      Like

Leave a comment