Sentry Answers>C#>

How to get int values from an enum in C#

How to get int values from an enum in C#

Richard C.

The Problem

A common task in C# is to get an enum value for a given integer or return the integer value of an enum for one of its values, or its name as a string.

For example, in the following enum, how would you print the string “Credit”, given the value 1 from a customer?

Click to Copy
public enum PaymentMethod { Credit = 1, Cash = 2, EFT = 3 }

The Solution

An enum value (the Credit = 1 part of PaymentMethod) has three parts:

  • The value as a whole (of typePaymentMethod)
  • An integer representation (1)
  • A string representation (the name Credit)

We need five different functions to convert between these three types. Here they are in one example using .NET 8:

Click to Copy
using System; public enum PaymentMethod { Credit = 1, Cash = 2, EFT = 3 } public class Program { public static void Main() { Console.WriteLine(GetEnumValueFromInt(1)); // Credit Console.WriteLine(GetEnumNameFromInt(1)); // "Credit", but this is a string Console.WriteLine(GetIntFromEnumValue(PaymentMethod.Cash)); // 2 Console.WriteLine(GetIntFromEnumName("Cash")); // 2 Console.WriteLine(GetEnumNameFromEnumValue(PaymentMethod.EFT)); // "EFT" } public static PaymentMethod GetEnumValueFromInt(int value) { return (PaymentMethod)value; } public static string GetEnumNameFromInt(int value) { return Enum.GetName((PaymentMethod)value); } public static int GetIntFromEnumValue(PaymentMethod paymentMethod) { return (int)paymentMethod; } public static int GetIntFromEnumName(string name) { return (int)Enum.Parse(typeof(PaymentMethod), name); } public static string GetEnumNameFromEnumValue(PaymentMethod paymentMethod) { return Enum.GetName(paymentMethod); } }

As you can see in the above code, it’s trivial to cast an enum value back and forth to an int. This is because an enum value is basically an int in .NET. However, more work is required in the methods using an enum name, because an enum value is not stored as a string in memory.

Error Handling

The methods above will fail if you pass values that are not in the range of the enum. However, your program might not crash — it might just continue running with completely incorrect values.

To fix this you should add an undefined enum element, to avoid returning a null value that might crash your program, and validate your inputs. Here’s an example:

Click to Copy
using System; public enum PaymentMethod { Undefined = -1, Credit = 1, Cash = 2, EFT = 3 } public class Program { public static void Main() { Console.WriteLine(GetEnumValueFromInt(5)); // Undefined Console.WriteLine(GetEnumNameFromInt(5)); // Undefined Console.WriteLine(GetIntFromEnumName("Bitcoin")); //-1 } public static PaymentMethod GetEnumValueFromInt(int value) { if (Enum.IsDefined(typeof(PaymentMethod), value)) return (PaymentMethod)value; return PaymentMethod.Undefined; } public static string GetEnumNameFromInt(int value) { if (Enum.IsDefined(typeof(PaymentMethod), value)) return Enum.GetName((PaymentMethod)value); return Enum.GetName(PaymentMethod.Undefined); } public static int GetIntFromEnumName(string name) { if (Enum.IsDefined(typeof(PaymentMethod), name)) return (int)Enum.Parse(typeof(PaymentMethod), name); return (int)PaymentMethod.Undefined; } }

An enum Value is Not Necessarily an int

An enum is an int by default, but it doesn’t have to be. An enum can use any integral type, like long or byte:

Click to Copy
public enum PaymentMethod : short { Credit = 1, Cash = 2, EFT = 3 }

This causes a problem with our conversion methods. They are set to use int. To handle every type of enum, we would have to rewrite all five methods to use long, short, byte, etc. Unfortunately, C# has no base type Integral that all integral types inherit from. This is because ints and longs are primitive types, not object types.

You might think you could use a long for every parameter in your functions because a long can fit any other integral. But unfortunately, .NET cannot automatically convert between an integral and an enum if the types aren’t identical. You’ll get the error System.ArgumentException: Enum underlying type and the object must be same type or object must be a String.

If you want to write a single set of functions that convert an enum of any type, you’ll have to use reflection:

Click to Copy
using System; public enum PaymentMethod : short { Undefined = 0, Credit = 1, Cash = 2, EFT = 3 } public class Program { public static void Main() { Console.WriteLine(GetEnumNameFromInt(1)); // Credit } public static string GetEnumNameFromInt(long value) { Type enumType = typeof(PaymentMethod); Type underlyingIntegralType = Enum.GetUnderlyingType(enumType); try { object convertedValue = Convert.ChangeType(value, underlyingIntegralType); if (Enum.IsDefined(enumType, convertedValue)) return Enum.GetName(enumType, convertedValue); } catch (OverflowException) { // Handle the case where the value is out of range for the underlying type } catch (InvalidCastException) { // Handle the case where the conversion is not possible } return Enum.GetName(enumType, PaymentMethod.Undefined); } }

First, we get the integral type of the enum with GetUnderlyingType, then we use Convert.ChangeType to convert our parameter to the same type as the enum. Now we can use it as we did in the previous methods.

Always Make Your enum ints Explicit

You can define an enum without specifying the integer values of each item. By default, they start at 0:

Click to Copy
public enum PaymentMethod { Undefined, Credit, Cash, EFT }

Don’t do this. Always give each item a number yourself.

There were old reports of different systems having the same enum values with different integer values. Although this is unlikely in modern .NET, it’s still possible for a programmer in your team to accidentally insert a value into the middle of an enum, breaking all the mappings of the subsequent enums, and causing errors when serializing your enums to ints in XML, JSON, or YAML documents you send to clients.

  • SentryC# Error and Performance Monitoring
  • Syntax.fmListen to the Syntax Podcast
  • Syntax.fm logo
    Listen to the Syntax Podcast

    Tasty treats for web developers brought to you by Sentry. Get tips and tricks from Wes Bos and Scott Tolinski.

    SEE EPISODES

Considered “not bad” by 4 million developers and more than 100,000 organizations worldwide, Sentry provides code-level observability to many of the world’s best-known companies like Disney, Peloton, Cloudflare, Eventbrite, Slack, Supercell, and Rockstar Games. Each month we process billions of exceptions from the most popular products on the internet.

© 2024 • Sentry is a registered Trademark
of Functional Software, Inc.