My adventures with enums
Like most things, it takes time to become proficient in using examples to design your code. Early on, one of the areas I forgot to cover in my fixtures was validating enum values. My tester would have a great time writing test cases like this:
BadClass bc = new BadClass();
bc.DayOfWeek = (DayOfWeek)(-1);
which would of course lead to Bad Things happening, because some GUI component would try to convert DayOfWeek
to a string and spontaneously self-combust. After the first time that type of bug got logged against me, it quickly became second nature to write a test before doing anything with an enum.
[Test]
[ExpectedException(typeof(ArgumentOutOfRangeException))]
public void SettingEnumToInvalidValueThrows()
{
GoodClass gc = new GoodClass();
gc.DayOfWeek = (DayOfWeek)(-1);
}
Coming from a C/C++ background, my check was done the naïve way.
class GoodClass
{
public DayOfWeek DayOfWeek
{
set
{
ValidateDayOfWeek(value);
dayOfWeek = value;
}
get { return dayOfWeek; }
}
private ValidateDayOfWeek(DayOfWeek value)
{
if (value != DayOfWeek.Sunday && value != DayOfWeek.Monday && .....)
{
throw new ArgumentOutOfRangeException("value");
}
}
}
Then today I was writing some enum-related code again and it suddenly struck me, "surely C# must have an easier way of doing this". Two seconds later and the answer presented itself: Enum.IsDefined()
. This makes my validation method look a bit nicer and I don't have to update it every time my enumeration changes.
private ValidateDayOfWeek(DayOfWeek value)
{
if (!Enum.IsDefined(typeof(DayOfWeek), value))
{
throw new ArgumentOutOfRangeException("value");
}
}
I know Rico Mariani (and many other people) always say to instrument your code before optimizing, but for some reason it struck me that Enum.IsDefined
might not be the fastest operation under the sun. So I took five minutes and threw together a console project to test my "naïve" validation routine against the built-in one.
The test used the nifty Stopwatch
class and executed each validation method one million times. I ran the entire test five times and took the overall average.
Validation by hand: .025 seconds
Validation using Enum.IsDefined(): 2.640 seconds
Looks like sticking to the old-fashioned way of validating an enum value is the way to go.
Also if you think about it, you probably do want to know if someone adds new values to the enumeration; there's no guarantee your code will work as expected for values that didn't exist when you originally wrote it.
Comments
- Anonymous
January 03, 2007
First off, let me wish everyone a Happy New Year and the best of luck with those millions of New Year's