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;
}
}
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.
- If you want Strings: Use a
static classwithconst string. - If you want Chars: Use
enum : ushortand cast the values. - If you want Floats: Use a
static classwithconst double. - Standard Usage: If you don't have a specific memory requirement, just use the default
enum Name { ... }which usesint.