Back to Blog
C#

C# enum to int: Cast, Convert, and Underlying Types

Learn how to convert C# enums to int values with explicit casts, Convert.ToInt32, and a clear understanding of underlying types and common pitfalls.

C#enumconversioncastingunderlying type.NET
Illustration of converting a C# enum to its integer value using a cast operator.

Converting a C# enum to int is a common operation when you need to store, transmit, or compare enum values numerically. The most direct way is an explicit cast, but there are nuances around the underlying type and invalid values that can affect correctness.

The Explicit Cast Is the Default Approach

In C#, an enum is a value type that has an underlying integral type. By default, that type is int. The simplest way to convert an enum value to its integer representation is an explicit cast:

enum Color { Red, Green, Blue } Color color = Color.Green; int value = (int)color; Console.WriteLine(value); // Output: 1

For an enum whose underlying type is int, this cast produces the underlying numeric value directly, without boxing or method calls. For enums with a different underlying type, the cast follows the same C# numeric-conversion rules as casting between the underlying integral types. This is recommended for most scenarios because it is direct, readable, and avoids conversion overhead.

The cast works regardless of the underlying type. If an enum is declared with a different underlying type, such as byte or long, the cast still produces a value according to C#'s conversion rules, but you must ensure the target type can hold it. For example:

enum ByteEnum : byte { A = 0, B = 1 } byte b = (byte)ByteEnum.B;

Here the cast to byte is safe because the underlying type is already byte. Casting to int would also work; the value would be widened from byte to int.

Using Convert.ToInt32 for Enum to Int

The Convert class provides a more general conversion method that works with any object implementing IConvertible. Since enums implement IConvertible, you can use Convert.ToInt32:

int value = Convert.ToInt32(Color.Blue);

This approach is useful when you are working with a value typed as object or when you need to handle conversions from multiple types in a uniform way. However, it comes with a cost: the enum value is boxed to an object before the conversion, which allocates memory. For a one-off conversion this is negligible, but in a hot loop it may be worth avoiding.

Convert.ToInt32 also respects the underlying type. If the enum's underlying type is long, the conversion still produces an int, but it may throw an OverflowException if the value exceeds the range of int. The explicit cast, by contrast, follows C#'s checked/unchecked conversion rules: in an unchecked context it can truncate, and in a checked context it can also throw. If the exact value matters and it may not fit in int, choose a wider target type or use a Convert method that returns that wider type.

Understanding the Underlying Type

Every enum has an underlying type that can be specified at declaration. The default is int, but you can use byte, sbyte, short, ushort, uint, long, or ulong. The underlying type determines the storage size and the range of representable values.

enum Status : byte { Inactive = 0, Active = 1 }

When converting to int, the value is widened from byte to int without issue. However, if the underlying type is ulong and the value is larger than int.MaxValue, an explicit cast to int will produce a value that is not meaningful because the value does not fit in int. In such cases, cast to the enum's underlying type or another sufficiently large type if you need the exact value.

The underlying type also matters when converting back from an integer: a value outside its range cannot be represented by the enum, and even an in-range value may not correspond to a named member.

Handling Invalid Enum Values

An enum variable can hold any value that fits its underlying type, even if that value is not defined in the enum declaration. This can happen when the value comes from an external source, such as deserialization or a database. When you convert such a value to an integer, you get the raw number, which may not correspond to any named constant.

enum Color { Red = 0, Green = 1, Blue = 2 } Color unknown = (Color)5; int value = (int)unknown; // 5

This is often the source of bugs if you assume the enum only contains defined values. If you need to validate that an integer is a defined enum value, use Enum.IsDefined(typeof(Color), value) before casting it to the enum type. Enum.IsDefined can be relatively expensive, so use it only where validation is actually required.

Performance and Allocation Considerations

When the enum's underlying type is already int, the explicit cast from enum to int is effectively a no-op at runtime: it does not box, call a method, or allocate. For other underlying types, the cast performs a numeric conversion, still without boxing or allocation. This makes the explicit cast the most efficient option for performance-sensitive code.

Convert.ToInt32, on the other hand, boxes the enum value because it accepts an object. The boxing allocation occurs even if the enum is already an int underneath. In tight loops or in code that processes a large number of enum values, this can add measurable overhead. If you are writing a library or a hot path, prefer the explicit cast.

For the reverse direction (string to enum), Enum.Parse or Enum.TryParse is comparatively expensive and should be used only when parsing from strings is actually required. For enum-to-int, the explicit cast is the clear winner.

Practical Usage Patterns

A common use case is storing an enum value in a database column that is an integer. You would convert the enum to an int before saving, and then convert back when reading. The explicit cast is straightforward:

int dbValue = (int)order.Status;

Another pattern is using an enum as a dictionary key or in a switch statement. While you can switch directly on the enum, you might need the integer value for logging or comparison with external systems.

int statusCode = (int)response.Status;

When you need to iterate over all values of an enum, you can use Enum.GetValues, but that returns an array whose elements are the enum type. Converting each element to int can be done with a cast in a loop.

Common Pitfalls and Edge Cases

One subtle pitfall is relying on the default values of an enum. If you do not explicitly assign values, the first member is 0, and subsequent members increment by 1. If you change the order or insert a new member, the integer values shift, which can break persisted data or external contracts. Always assign explicit values if the enum represents a stable contract.

Another edge case is an enum with a Flags attribute. Flags enums are used for bitwise combinations, and for a flags enum with an int underlying type, converting to int is still valid, but you must ensure the integer representation is meaningful. For example, [Flags] enum Permissions { None = 0, Read = 1, Write = 2, Execute = 4 }. Converting a combination like Read | Write to int yields 3. This is expected, but you should be careful when comparing such values.

Finally, consider the Enum base class methods. Enum.GetName and Enum.GetNames work with the enum type and return strings, not integers. If you need the integer value for a given name, you can use Enum.Parse and then cast, but that is a roundabout way. When you already have an enum value, the direct cast is the simplest option.

How to Convert a C# enum to int | RYUSLOG DEV