enum
string conversion
programming
software development
code optimization

Getting value of enum on string conversion

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

When an enum becomes a string, developers often expect "the value" and then discover that there are several possible values: the member name, the underlying number, or a custom label used for display or serialization. In C#, those are different representations, and treating them as interchangeable usually causes bugs at API boundaries.

ToString() Returns the Member Name

The default behavior is simple: ToString() returns the symbolic name of the enum member when one exists. That is useful for logging and debugging, but it is not the same thing as the underlying numeric value.

csharp
1using System;
2
3public enum OrderStatus
4{
5    Pending = 1,
6    Approved = 2,
7    Rejected = 3
8}
9
10public class Program
11{
12    public static void Main()
13    {
14        var status = OrderStatus.Approved;
15
16        Console.WriteLine(status.ToString());
17        Console.WriteLine((int)status);
18    }
19}

The output is Approved and then 2. That distinction is the core answer to most questions in this area: string conversion is about the enum name unless you explicitly choose something else.

Decide Which Value You Actually Need

Most enum confusion comes from asking for "the value" without deciding which representation the application wants. In practice there are three separate use cases:

  • The code-facing name for logs and diagnostics.
  • The numeric value for storage or interop.
  • A custom text token for UI or external contracts.

If you need the numeric value, cast explicitly and then convert that number to text:

csharp
int code = (int)OrderStatus.Approved;
string text = code.ToString();
Console.WriteLine(text);

That is clearer than relying on formatting side effects, and it tells the next maintainer exactly what contract you intended.

This is why enum conversion bugs often show up at API edges. The code inside the application thinks in enum members, while storage or transport layers often want numbers or stable custom strings.

Parse Strings Back Safely

If you receive text that should match enum member names, use Enum.TryParse. It avoids exception-driven control flow and makes invalid input an ordinary branch instead of a crash.

csharp
1using System;
2
3public enum Priority
4{
5    Low,
6    Medium,
7    High
8}
9
10public class Program
11{
12    public static void Main()
13    {
14        string input = "high";
15
16        if (Enum.TryParse<Priority>(input, ignoreCase: true, out var priority))
17        {
18            Console.WriteLine($"Parsed: {priority}");
19        }
20        else
21        {
22            Console.WriteLine("Invalid priority");
23        }
24    }
25}

This works only when your external text matches the enum member names. If the contract uses different tokens such as high_priority, you need a mapping layer.

Use Explicit Mappings for Custom String Values

Custom string values should be designed, not inferred. One common approach is to attach attributes and read them with reflection.

csharp
1using System;
2using System.ComponentModel;
3using System.Reflection;
4
5public enum PaymentState
6{
7    [Description("awaiting_payment")]
8    Pending,
9
10    [Description("payment_received")]
11    Paid,
12
13    [Description("payment_failed")]
14    Failed
15}
16
17public static class EnumTextExtensions
18{
19    public static string GetDescription(this Enum value)
20    {
21        var field = value.GetType().GetField(value.ToString());
22        var attribute = field?.GetCustomAttribute<DescriptionAttribute>();
23        return attribute?.Description ?? value.ToString();
24    }
25}
26
27public class Program
28{
29    public static void Main()
30    {
31        Console.WriteLine(PaymentState.Pending.GetDescription());
32    }
33}

This keeps code names, display text, and wire-format values separate. That separation matters because renaming an enum member for readability should not silently break stored data or public API clients.

Flags Enums Are a Special Case

With [Flags], string conversion may produce a comma-separated list of names rather than a single token. That is helpful for diagnostics but poor as a long-term persisted format.

csharp
1using System;
2
3[Flags]
4public enum Permissions
5{
6    None = 0,
7    Read = 1,
8    Write = 2,
9    Delete = 4
10}
11
12public class Program
13{
14    public static void Main()
15    {
16        var permissions = Permissions.Read | Permissions.Write;
17        Console.WriteLine(permissions.ToString());
18        Console.WriteLine((int)permissions);
19    }
20}

If an enum crosses JSON, database, or message boundaries, choose the format explicitly and keep it stable.

In other words, ToString() can be fine for logs, but it is a weak long-term contract for persistence unless you deliberately want name-based serialization.

Common Pitfalls

  • Expecting ToString() to return the underlying integer.
  • Using enum member names as public API values and later renaming them.
  • Parsing external input with Enum.Parse instead of TryParse.
  • Mixing display labels, persisted values, and code names in the same field.
  • Assuming flags enum output is a single stable token.

Summary

  • In C#, enum string conversion normally returns the member name.
  • Cast to the underlying type when you need the numeric value.
  • Use Enum.TryParse for safe reverse conversion from text.
  • Create explicit mappings for display labels or wire-format values.
  • Treat logging text, serialized values, and code-facing names as separate concerns.

Course illustration
Course illustration

All Rights Reserved.