Enum.TryParse unexpected behavior

17/08/2023

Enums 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.

8
An error has occurred. This application may no longer respond until reloaded. Reload x