Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / VB

Setting Enumerators From Questionable Data Sources (for C# and VB)

5.00/5 (6 votes)
9 Jul 2011CPOL2 min read 17.8K  
Avoid exceptions when setting enumerators from unknown/untrusted sources.

Introduction


This was originally posted in the Wicked Code forum, but that was before Tips/Tricks came into vogue, so I moved it here.

I started programming almost 30 years ago. Over that time, I've grown to have a huge distrust of not only users and their antics, but also other programmers and their seeming apathy toward ensuring that data is valid before trying to use it.

Why We're Here (For the C# Devs)


One of the problems I encountered with .Net was storing and retrieving enumerator values in data sources, and preparing the code to gracefully handle manually converting values - either modified by the user, incorrectly set or interpreted by the programmer, or refactored without appropriate notice to those programmers. To save myself a lot of time, I came up with a couple of methods that I include in pretty much every program I write:

public static T IntToEnum<T>(int value, T defaultValue)
{
    T enumValue = (Enum.IsDefined(typeof(T), value)) ? (T)(object)value 
                                                     : defaultValue;
    return enumValue;
}

The purpose of the method is to allow the programmer to initialize a data member of a specified enumerator type to a value contained in the ordinal list. The problem this method addresses is that if the programmer retrieves an enum ordinal value as an int type, and wants to initialize an enum data member, he really has no programmatic idea if the value represents a valid ordinal. He simply tries to set it, and hopes for the best (handling an exception if the assignment goes sideways on him).

This method allows the programmer to make the same attempt but with controlled results, thereby avoiding the inevitable exception generated when an invalid ordinal value is used. Usage goes something like this:
enum SomeEnum { Zero=0, Five=5, Six=6, Eight=8 };

// this will result in the correct expected value - SomeEnum.Five
SomeEnum value = IntToEnum(5, SomeEnum.Zero);

// this will result in SomeEnum.Zero because the value (4) isn't a 
// valid ordinal in the enumerator
value = IntToEnum(4, SomeEnum.Zero);

Fine, right? But what if the enum value was stored as a string? I have an answer for you, and it looks a lot like the first one.
public static T StringToEnum<T>(string value, T defaultValue)
{
    T enumValue = (Enum.IsDefined(typeof(T), value)) ? 
                   (T)Enum.Parse(typeof(T), value) : 
                   defaultValue;
    return enumValue;
}

Given the enum defined in the first usage example, you would do something like this:
// this will result in the correct expected value - SomeEnum.Five
SomeEnum value = StringToEnum("5", SomeEnum.Zero);

// this will result in SomeEnum.Zero because the value (4) isn't a 
// valid ordinal in the enumerator
value = StringToEnum("4", SomeEnum.Zero);

And For The VB.Net Devs


Recently, I held a job that forced me to code in VB.Net. For all the VB.Net people out there, here's the same code converted to your preferred/forced language:
Public Shared Function IntToEnum(Of T)(value As Integer, defaultValue As T) As T
    Dim enumValue As T = If(([Enum].IsDefined(GetType(T), value)), _
                             DirectCast(DirectCast(value, Object), T), _
                             defaultValue)
    Return enumValue
End Function

Public Shared Function StringToEnum(Of T)(value As String, defaultValue As T) As T
    Dim enumValue As T = If(([Enum].IsDefined(GetType(T), value)), _
                            DirectCast([Enum].Parse(GetType(T), value), T), _
                            defaultValue)
    Return enumValue
End Function

Closing Comment


For every approach to a given problem, there are many varied implementations that can be coded. Some of you may prefer the TryParse/handle error method to implementing this particular code, and that's fine. That's what's so cool about coding. You can hit the same problem from wildly different angles and still be right.

Edits



09 Jul 2011 = Fixed a pointy bracket display problem in a code snippet, as well as a couple of misspellings.

05 May 2010 - The string version is different in Silverlight 3. You need to add a third parameter to the Parse method call that indicates whether or not you want to honor case sensitivity.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)