Question
Given a C# enum, how can I create a list containing all values declared by that enum?
For example:
public enum Status
{
Pending,
Approved,
Rejected
}
How can I obtain a List<Status> containing Pending, Approved, and Rejected?
Short Answer
You will learn how C# enums store a fixed set of named values, how to retrieve those values with Enum.GetValues, and how to convert the result into a strongly typed List<T>. You will also learn important details about enum aliases, [Flags] enums, and display-friendly names.
Concept
An enum (enumeration) defines a fixed set of named constants. It is useful when a value must be one of a known set of choices, such as an order status, user role, or payment method.
C# provides Enum.GetValues to retrieve the values declared by an enum type. In modern C#, the generic overload is the clearest option:
Status[] statuses = Enum.GetValues<Status>();
The method returns an array. Since an array and a List<T> are different collection types, use ToList() when a list is specifically required:
List<Status> statuses = Enum.GetValues<Status>().ToList();
This matters because you should not manually maintain a separate list of enum values. If a new member is added to the enum later, Enum.GetValues<Status>() automatically includes it.
Mental Model
Think of an enum as a menu printed by a restaurant:
- The enum declaration is the official menu.
- Each enum member is one menu item.
Enum.GetValues<Status>()asks for every item currently printed on that menu.ToList()puts those items into a reusable, editable container.
Instead of writing the menu again by hand in another place, read it from the original source of truth: the enum.
Syntax and Examples
Use Enum.GetValues<TEnum>() to get all values, then call ToList() if you need a list.
using System;
using System.Collections.Generic;
using System.Linq;
public enum Status
{
Pending,
Approved,
Rejected
}
List<Status> statuses = Enum.GetValues<Status>().ToList();
foreach (Status status in statuses)
{
Console.WriteLine(status);
}
Output:
Pending
Approved
Rejected
Enum.GetValues<Status>() returns a Status[]. ToList() is a LINQ extension method, so include:
using System.Linq;
If you only need to loop through the values, you do not need to create a list:
foreach (Status status in Enum.GetValues<Status>())
{
Console.WriteLine(status);
}
For older C# or .NET versions that do not support the generic overload, use the type-based overload and cast the result:
List<Status> statuses = Enum.GetValues(typeof(Status))
.Cast<Status>()
.ToList();
Step by Step Execution
Consider this code:
public enum Priority
{
Low,
Medium,
High
}
Priority[] priorities = Enum.GetValues<Priority>();
List<Priority> priorityList = priorities.ToList();
Step by step:
-
Prioritydeclares three possible values:Low,Medium, andHigh. -
Enum.GetValues<Priority>()examines thePriorityenum type. -
It creates an array containing every declared enum value:
[Priority.Low, Priority.Medium, Priority.High] -
The array is assigned to
priorities. -
priorities.ToList()creates a newList<Priority>with the same items. -
priorityListcan now use list operations such asCount, indexing, orAdd. In most cases, however, you should treat enum options as fixed and avoid adding values that were not declared in the enum.
Real World Use Cases
Common uses for enumerating an enum include:
- Dropdown menus: Show all supported order statuses in an admin dashboard.
- API validation: Check whether an incoming value is one of the allowed application states.
- Configuration screens: Let a user choose a theme, language mode, or notification frequency.
- Reports: Group records by every possible category, including categories with zero records.
- Test data: Run the same test against each supported enum value.
- Command-line tools: Display all available output formats or execution modes.
Example: creating options for a UI model:
public enum ShippingMethod
{
Standard,
Express,
Pickup
}
List<ShippingMethod> options = Enum.GetValues<ShippingMethod>().ToList();
Real Codebase Usage
In production code, developers often enumerate enums at application boundaries: UI forms, request validation, serialization, and configuration. Keep the enum itself as the source of truth.
Return a read-only collection when callers should not change it
using System;
using System.Collections.Generic;
public static class StatusOptions
{
public static IReadOnlyList<Status> All { get; } = Array.AsReadOnly(
Enum.GetValues<Status>()
);
}
This communicates that callers may read the available options but should not modify the collection.
Validate an enum value
An enum variable can hold a numeric value that was never declared, especially when data comes from an API, database, or integer cast.
public static bool IsValidStatus(Status status)
{
return Enum.IsDefined(status);
}
Build display data separately
Enum names are often developer-oriented. A UI usually needs a label:
var options = Enum.GetValues<Status>()
.Select(status => new
{
Value = status,
Label = status.ToString()
})
.ToList();
For user-facing labels, many projects use attributes, resource files, or a dedicated mapping method rather than exposing raw enum names directly.
Common Mistakes
Forgetting that GetValues returns an array
This does not compile because the method returns Status[], not List<Status>:
// Broken
List<Status> statuses = Enum.GetValues<Status>();
Convert it explicitly:
List<Status> statuses = Enum.GetValues<Status>().ToList();
Manually duplicating enum members in a list
// Fragile: this becomes outdated when the enum changes.
var statuses = new List<Status>
{
Status.Pending,
Status.Approved,
Status.Rejected
};
Prefer Enum.GetValues<Status>(), which updates automatically when the enum changes.
Using ToString() as a user-friendly label
Console.WriteLine(Status.Pending.ToString()); // "Pending"
This is fine for logs and debugging, but UI text may need spaces, localization, or business wording. Map enum values to display labels deliberately.
Assuming enum values are always sequential
public enum HttpResult
{
Ok = 200,
NotFound = 404
}
Do not loop from 0 to a maximum integer. Enum values can have explicit numbers, gaps, negative values, and aliases. Use Enum.GetValues.
Ignoring duplicate numeric values (aliases)
public enum Result
{
Success = 0,
Ok = 0,
Failed = 1
}
Success and Ok represent the same underlying numeric value. Do not assume each returned value is a unique numeric value. If your logic requires unique numeric values, apply Distinct():
List<Result> uniqueValues = Enum.GetValues<Result>()
.Distinct()
.ToList();
Treating [Flags] combinations as declared options
A flags enum can represent combinations such as Read | Write. Enum.GetValues returns declared constants, not every possible combination. Generate combinations only when your application genuinely needs them.
Comparisons
| Approach | Result | Best use |
|---|---|---|
Enum.GetValues<Status>() | Status[] | Looping over every enum value |
Enum.GetValues<Status>().ToList() | List<Status> | When list-specific APIs are required |
Enum.GetNames<Status>() | string[] | Getting member names rather than values |
Enum.GetValues(typeof(Status)).Cast<Status>() | Enumerable of Status | Older C# or .NET codebases |
Manual new List<Status> { ... } | Hand-maintained list | Only when intentionally showing a subset or custom order |
GetValues returns enum values:
Status[] values = Enum.GetValues<Status>();
GetNames returns strings:
string[] names = Enum.GetNames<Status>();
Use values when your program will compare, store, or process the enum. Use names when you specifically need text identifiers.
Cheat Sheet
using System.Linq;
// All values as an array
Status[] values = Enum.GetValues<Status>();
// All values as a list
List<Status> list = Enum.GetValues<Status>().ToList();
// Loop without allocating a list
foreach (Status value in Enum.GetValues<Status>())
{
Console.WriteLine(value);
}
// Older type-based syntax
List<Status> oldStyle = Enum.GetValues(typeof(Status))
.Cast<Status>()
.ToList();
// Get names instead of values
string[] names = Enum.GetNames<Status>();
// Check whether a value is declared
bool valid = Enum.IsDefined(Status.Pending);
Key rules:
Enum.GetValues<TEnum>()returns an array.- Call
ToList()only when you need a mutableList<T>. - Include
using System.Linq;forToList(),Cast(),Select(), andDistinct(). - Enum numeric values do not have to start at zero or be consecutive.
- Be careful with aliases and
[Flags]enums.
FAQ
How do I get all enum values in C#?
Use Enum.GetValues<TEnum>():
Status[] values = Enum.GetValues<Status>();
How do I convert Enum.GetValues to a List<T>?
Call ToList():
List<Status> values = Enum.GetValues<Status>().ToList();
Why does ToList() not work in my C# code?
ToList() is a LINQ extension method. Add using System.Linq; and ensure your project references the standard LINQ libraries.
Do I need a list to loop through enum values?
No. Loop directly over the array returned by Enum.GetValues<TEnum>().
foreach (Status status in Enum.GetValues<Status>())
{
Console.WriteLine(status);
}
Does Enum.GetValues include every [Flags] combination?
No. It returns the constants explicitly declared in the enum. Combinations such as Read | Write are not automatically generated.
Can an enum contain duplicate values?
Yes. Multiple member names can use the same underlying number. Treat aliases carefully when displaying or counting values.
Is Enum.GetValues(typeof(MyEnum)) still valid?
Yes. It is useful in older code, but Enum.GetValues<MyEnum>() is clearer and strongly typed in modern C#.
Mini Project
Description
Create a small console program that displays every available order status and verifies whether an order status received as a number is defined by the enum. This reflects a common boundary in real applications, where values may come from forms, APIs, or databases.
Goal
Enumerate enum values into a list and safely validate a selected status.
Requirements
- Define an
OrderStatusenum with at least three values. - Create a
List<OrderStatus>containing all declared enum values. - Print each available status.
- Read a numeric status value from the console.
- Report whether the supplied value is a declared
OrderStatus.
Keep learning
Related questions
AddTransient vs AddScoped vs AddSingleton in ASP.NET Core Dependency Injection
Learn the differences between AddTransient, AddScoped, and AddSingleton in ASP.NET Core DI with examples and practical usage.
Best Way to Repeat a Character in C#: Building Repeated Strings Efficiently
Learn the best way to repeat a character in C#, compare StringBuilder, string concatenation, and simpler built-in options.
C# Access Modifiers and static: public, private, protected, and Defaults
Learn how C# public, private, protected, and default access control visibility, and how static differs from instance members.