Skip to main content

How to Resolve Error "CS1008: Type byte, sbyte, short, ushort, int, uint, long, or ulong expected" in C#

The Compiler Error CS1008 is a restriction error specific to Enum declarations. The message reads: "Type byte, sbyte, short, ushort, int, uint, long, or ulong expected".

In C#, an enum (Enumeration) is a value type defined by a set of named constants of the underlying integral numeric type. By default, this underlying type is int. You are allowed to change it to other specific integer types to save memory or match external data formats. However, you strictly cannot use non-integral types like string, char, float, or bool as the backing type for an enum.

This guide explains how to handle situations where you want an enum to behave like a string or a character.

Understanding Enum Backing Types

When you declare enum Status : byte, you are telling the compiler: "Every value in Status is actually a byte in memory."

The C# specification limits the valid backing types to the 8 integer primitives:

  • byte, sbyte (8-bit)
  • short, ushort (16-bit)
  • int, uint (32-bit)
  • long, ulong (64-bit)

Any type outside this list triggers CS1008.

Scenario 1: Attempting String Enums

Developers coming from languages like TypeScript, Java, or Python often try to define enums that map directly to strings. C# does not support this natively in the enum syntax.

Example of error

// ⛔️ Error CS1008: Type byte, sbyte, ... expected.
// 'string' is a reference type, not an integral type.
public enum UserRole : string
{
Admin = "ADMIN_ROLE",
Guest = "GUEST_ROLE"
}

Solution: Use Static Constants

The standard C# pattern ("String Enum") is to use a static class with constant string fields.

// ✅ Correct: Defines a group of related string constants.
public static class UserRole
{
public const string Admin = "ADMIN_ROLE";
public const string Guest = "GUEST_ROLE";
}

public class Program
{
static void Main()
{
// Usage looks very similar to an enum
string myRole = UserRole.Admin;
}
}
note

Alternative: If you need to keep the enum for type safety (so functions can take UserRole instead of just string), define a normal int enum and use the [Description] attribute or a switch expression extension method to map the values to strings.

Scenario 2: Attempting Character (char) Enums

The char type in C# is technically a 16-bit integer (representing a Unicode character). However, the C# specification explicitly excludes char from the list of valid enum bases to avoid ambiguity between numeric operations and text operations.

Example of error

// ⛔️ Error CS1008: 'char' is not in the allowed list of types.
public enum Grade : char
{
A = 'A',
B = 'B',
C = 'C'
}

Solution: Use ushort or int

Since char is 16-bit, ushort (unsigned short) is the exact memory equivalent. You can still assign character literals to the members because char implicitly converts to numeric types.

// ✅ Correct: 'ushort' fits the size of a char exactly.
public enum Grade : ushort
{
// C# automatically converts the char literal 'A' (65) to the number 65.
A = 'A',
B = 'B',
C = 'C'
}

public class Program
{
static void Main()
{
Grade myGrade = Grade.A;

// To see it as a character, simply cast it back
Console.WriteLine((char)myGrade); // Output: A
}
}

Scenario 3: Attempting Floating Point Enums

You cannot use float, double, or decimal as a backing type. Enums are discrete values, whereas floating-point numbers are continuous approximations, making them unsuitable for enumeration.

Example of error

// ⛔️ Error CS1008: 'double' is not an integral type.
public enum MathConst : double
{
Pi = 3.14,
E = 2.71
}

Solution: Use Static Constants

Just like with strings, create a class to hold these values.

public static class MathConst
{
// ✅ Correct: Group constants in a static class
public const double Pi = 3.14;
public const double E = 2.71;
}

Conclusion

CS1008 protects the internal structure of Enums, ensuring they remain simple, efficient integers.

  1. If you want Strings: Use a static class with const string.
  2. If you want Chars: Use enum : ushort and cast the values.
  3. If you want Floats: Use a static class with const double.
  4. Standard Usage: If you don't have a specific memory requirement, just use the default enum Name { ... } which uses int.