Enum
s are very simple structures, but some functions like Enum.TryParse
can have unexpected behavior. In this short blog post, we discover why and what are the alternatives.
Enum.TryParse
Enum.TryParse
does the following:
Converts the string representation of the name or numeric value of one or more enumerated constants to an equivalent enumerated object. The return value indicates whether the conversion succeeded.
So if we have an enumeration like this:
public enum WeekendDay
{
Saturday = 0,
Sunday = 1,
}
And we call the function like so:
var couldParse = Enum.TryParse("1", out WeekendDay weekendDay);
Console.WriteLine($"Could parse: {couldParse}");
Console.WriteLine($"Value: {weekendDay}");
public enum WeekendDay
{
Saturday = 0,
Sunday = 1,
}
We get the following result:
Could parse: True
Value: Sunday
Seems reasonable - but here is the interesting part, if you specify a value that is not part of your enum, it still works:
using System;
var couldParse = Enum.TryParse("3", out WeekendDay weekendDay);
Console.WriteLine($"Could parse: {couldParse}");
Console.WriteLine($"Value: {weekendDay}");
public enum WeekendDay
{
Saturday = 0,
Sunday = 1,
}
This prints out:
Could parse: true
Value: 3
Where Value: 3
might makes sense, as you can also do things like var myValue = (WeekendDay)3;
it seems odd that it returns true
and tells you that it could parse it without problem.
The fix
Use Enum.IsDefined
to check if a given value is in the correct range. With Enum.IsDefined
we can check if the value is correct for a given enum.
var couldParse = Enum.TryParse("3", out WeekendDay weekendDay);
if (couldParse && Enum.IsDefined(typeof(WeekendDay), weekendDay))
{
// Only here do we have a valid value for WeekendDay
}
In our case, we will not enter the if block— one of the many shortcomings of the "simple enum" type. That is why I had an article over two years ago in this blog: "A better enumeration - Type safe from start to end" which, as of today, I still use in this shape or another in some of my projects. Obviously, many cool libraries tackle that exact problem with an enumeration class in some way or another - so depending on your needs, you don't have to role out your own implementation.