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 };
SomeEnum value = IntToEnum(5, SomeEnum.Zero);
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:
SomeEnum value = StringToEnum("5", SomeEnum.Zero);
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.