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.

The garbage collector in .NET

This article will talk about the garbage collector in .NET. Why do we have and need him? And why it is essential to understand the behavior to know what impact on our application he has.

Enum.Equals - Performance analysis

Did you know that you can spend 100x times longer depending how you compare your enums?

Of course we are speaking here in terms of nanoseconds but this story is much more then just numbers. We'll also talk about boxing and unboxing. So let's dive right into it.

A better enumeration - Type safe from start to end

Enumerations are one of the fundamental value types in C#. enum's are handy if you have a constrained set of allowed values. But the enum type also has a lot of drawbacks. Personally, one major issue for me is that you can't define methods inside the enum. Plus, you can just pass them invalid values and it just works (Todd Howard I'm looking at you).

So why not make a lightweight alternative which removes a lot of the shortcomings of an enum?

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