How to Convert a String to an Enum and back in C#

Dec 17, 2025 • Chris Pietschmann  • C#

Enums are great for making code more readable and less error-prone than passing around “magic strings” or numbers. But in the real world, strings still happen — config files, query strings, JSON payloads, environment variables, user input, etc.

In this post, I’ll show a few practical ways to convert a string → enum, how to validate safely (without exceptions), and how to convert an enum → string in a couple different formats.


What is an enum?

An enum is a named set of constants. By default, the underlying type is int, and values start at 0 unless you specify otherwise.

public enum WeekDays
{
    Sunday = 0,
    Monday = 1,
    Tuesday = 2,
    Wednesday = 3,
    Thursday = 4,
    Friday = 5,
    Saturday = 6
}

Convert a string to an enum

1) Enum.Parse (simple, but throws on bad input)

If you already know the input is valid (or you’re fine with exceptions), Enum.Parse is the most direct option.

string dayName = "Friday";

WeekDays day = (WeekDays)Enum.Parse(typeof(WeekDays), dayName);
Console.WriteLine(day); // Friday

Case sensitivity: by default, Enum.Parse is case-sensitive.

string dayName = "friday";

// Throws ArgumentException (case-sensitive by default)
WeekDays day = (WeekDays)Enum.Parse(typeof(WeekDays), dayName);

To ignore case:

string dayName = "friday";

WeekDays day = (WeekDays)Enum.Parse(typeof(WeekDays), dayName, ignoreCase: true);
Console.WriteLine(day); // Friday

For anything involving external input, Enum.TryParse is usually the better choice.

string dayName = "Friday";

if (Enum.TryParse(dayName, out WeekDays day))
{
    Console.WriteLine(day); // Friday
}
else
{
    Console.WriteLine("Invalid day name!");
}

If you want case-insensitive parsing:

string dayName = "friday";

if (Enum.TryParse(dayName, ignoreCase: true, out WeekDays day))
{
    Console.WriteLine(day); // Friday
}

A subtle gotcha: numeric strings also parse

One “surprise” is that Enum.TryParse (and Enum.Parse) can accept numeric strings too.

string input = "4";

if (Enum.TryParse(input, out WeekDays day))
{
    Console.WriteLine(day); // Thursday (because Thursday = 4)
}

And if the numeric value is not defined, parsing can still succeed — you’ll get an enum value that has no named member:

string input = "10";

if (Enum.TryParse(input, out WeekDays day))
{
    Console.WriteLine(day); // 10
}

So if you need to enforce “must be one of the defined enum values”, you’ll want validation.


Validate that the parsed value is actually defined

Using Enum.IsDefined (works well for non-Flags enums)

string input = "10";

if (Enum.TryParse(input, out WeekDays day) && Enum.IsDefined(typeof(WeekDays), day))
{
    Console.WriteLine(day);
}
else
{
    Console.WriteLine("Not a defined WeekDays value.");
}

This is a good way to prevent “random numbers in an enum suit”.


Convert an enum back to a string

1) ToString() (the common case)

WeekDays day = WeekDays.Friday;

string text = day.ToString();
Console.WriteLine(text); // Friday

If the enum value doesn’t have a named member (like 10), ToString() returns the numeric text:

WeekDays day = (WeekDays)10;
Console.WriteLine(day.ToString()); // 10

2) Format strings: "G", "D", "X", and "F"

The Enum.ToString(string format) overload gives you a few useful options.

WeekDays day = WeekDays.Friday;

Console.WriteLine(day.ToString("G")); // Friday (General)
Console.WriteLine(day.ToString("D")); // 5      (Decimal)
Console.WriteLine(day.ToString("X")); // 00000005 (Hex)

Working with [Flags] enums

Flags enums represent combinations of values and are typically parsed from comma-separated strings.

[Flags]
public enum FilePermissions
{
    None = 0,
    Read = 1,
    Write = 2,
    Execute = 4
}

Parse a flags string

string input = "Read, Write";

if (Enum.TryParse(input, ignoreCase: true, out FilePermissions perms))
{
    Console.WriteLine(perms); // Read, Write
}

Convert flags to string

FilePermissions perms = FilePermissions.Read | FilePermissions.Write;

Console.WriteLine(perms.ToString("G")); // Read, Write
Console.WriteLine(perms.ToString("D")); // 3
Console.WriteLine(perms.ToString("F")); // Read, Write

Note: Enum.IsDefined is usually not the right validator for flags combinations, because a combination (like Read | Write) may be valid even if you never defined a named member with value 3.

Validate a flags value using a bitmask

A common approach is: ensure no bits are set outside the allowed flags.

static bool IsValidFlags<TEnum>(TEnum value) where TEnum : struct, Enum
{
    ulong raw = Convert.ToUInt64(value);

    // Build a mask of all defined values in the enum.
    ulong mask = 0;
    foreach (var v in Enum.GetValues<TEnum>())
    {
        mask |= Convert.ToUInt64(v);
    }

    // If value contains bits not present in the mask, it's invalid.
    return (raw & ~mask) == 0;
}

Usage:

string input = "Read, Write";

if (Enum.TryParse(input, ignoreCase: true, out FilePermissions perms) && IsValidFlags(perms))
{
    Console.WriteLine(perms); // Read, Write
}
else
{
    Console.WriteLine("Invalid permissions value.");
}

Generic helper methods

If you do this a lot, wrapping it up can keep your code tidy.

Safe parse (returns bool)

public static bool TryToEnum<TEnum>(string? input, out TEnum value, bool ignoreCase = true)
    where TEnum : struct, Enum
{
    value = default;

    if (string.IsNullOrWhiteSpace(input))
        return false;

    if (!Enum.TryParse(input, ignoreCase, out value))
        return false;

    // Prevent "10" from becoming a non-defined enum value (for non-Flags enums).
    if (!typeof(TEnum).IsDefined(typeof(FlagsAttribute), inherit: false))
        return Enum.IsDefined(typeof(TEnum), value);

    // For Flags enums, allow combinations but reject unknown bits.
    return IsValidFlags(value);
}

Parse-or-default (handy for config)

public static TEnum ToEnumOrDefault<TEnum>(string? input, TEnum defaultValue, bool ignoreCase = true)
    where TEnum : struct, Enum
{
    return TryToEnum<TEnum>(input, out var value, ignoreCase) ? value : defaultValue;
}

Wrap-up

  • Use Enum.TryParse for anything that might be invalid input.
  • Remember: numeric strings can parse successfully, even if the value isn’t defined.
  • Validate with Enum.IsDefined for non-flags enums.
  • For [Flags], validate using a bitmask so legitimate combinations still pass.
  • Use ToString() (or format strings like "D" / "X") to convert back to a string.

That’s it — string ↔ enum conversions without surprises.