Question
Const vs Readonly in C#: What's the Difference and When to Use Each
Question
In C#, what is the difference between const and readonly?
When should you use one instead of the other?
Short Answer
By the end of this page, you will understand how const and readonly work in C#, when their values are assigned, what kinds of values they can store, and which one to choose in real projects.
Concept
const and readonly both help you create values that should not be changed, but they are not the same.
const
A const field is a compile-time constant.
That means:
- Its value must be known when the code is compiled.
- You must assign it immediately where it is declared.
- Its value can never change.
- It is implicitly
static, so it belongs to the type itself, not to each object.
Example:
public class AppSettings
{
public const int MaxUsers = 100;
}
100 is known at compile time, so it works as a const.
readonly
A readonly field is a value that can be assigned only during initialization or in a constructor.
That means:
- The value does not need to be known at compile time.
- It can be different for each object.
- It can be set when the object is created.
- It can also be
static readonlyif you want one shared value for the whole type.
Example:
public class User
{
public readonly DateTime CreatedAt;
public User()
{
CreatedAt = DateTime.Now;
}
}
DateTime.Now is only known at runtime, so it cannot be const, but it can be readonly.
Why this matters
Choosing the right one affects:
- correctness
- maintainability
- versioning between assemblies
- whether values can be computed at runtime
A good rule is:
- Use
constfor true fixed values that will never change and are known at compile time. - Use
readonlyfor values that should not change after construction but are determined at runtime or may vary by instance.
Mental Model
Think of const as text printed directly into every copy of a document before it is distributed.
- The value is decided once during printing.
- It cannot depend on anything that happens later.
- Every reader sees the exact same printed value.
Think of readonly as filling in a form when each object is created.
- You can decide the value at creation time.
- After the form is filled out, it cannot be changed.
- Different objects can have different values.
So:
const= printed into the program at compile timereadonly= assigned once at initialization/runtime, then locked
Syntax and Examples
Core syntax
const
public class MathValues
{
public const double Pi = 3.14159;
}
Rules:
- Must be assigned at declaration
- Must use a compile-time constant value
- Is automatically
static
readonly
public class Config
{
public readonly string EnvironmentName;
public Config(string environmentName)
{
EnvironmentName = environmentName;
}
}
Rules:
- Can be assigned at declaration, or
- Can be assigned inside the constructor
- Cannot be reassigned later
Example: const for a fixed application value
public class HttpStatus
{
public const int NotFound = 404;
}
This is a good const because 404 is a fixed value known at compile time.
Example: readonly for runtime data
public class Report
{
public readonly DateTime GeneratedAt;
public Report()
{
GeneratedAt = DateTime.Now;
}
}
This must be readonly, not const, because DateTime.Now is only available when the program runs.
Example: static readonly
public class Paths
{
public static readonly string LogDirectory = AppDomain.CurrentDomain.BaseDirectory + "logs";
}
Use static readonly when:
- the value belongs to the class, not each object
- the value is set once
- the value is only known at runtime
Step by Step Execution
Consider this code:
public class Example
{
public const int FixedValue = 10;
public readonly int InstanceValue;
public Example(int value)
{
InstanceValue = value;
}
}
var a = new Example(5);
var b = new Example(9);
Here is what happens step by step:
- The compiler sees
FixedValueand stores10as a compile-time constant. FixedValuebelongs to the class itself, not to objectsaorb.- When
new Example(5)runs, the constructor is called. - Inside the constructor,
InstanceValueis assigned5. - When
new Example(9)runs, a new object is created. - Its
InstanceValueis assigned9.
So the results are:
Example.FixedValueis always10a.InstanceValueis5b.InstanceValueis9
This shows the key difference:
constis one fixed compile-time valuereadonlycan be assigned during object creation
Real World Use Cases
When const is useful
Use const for values that are truly fixed forever, such as:
- mathematical values used in your code
- unit conversion values
- fixed application labels
- known protocol values that will not change
Example:
public class Units
{
public const int DaysPerWeek = 7;
}
When readonly is useful
Use readonly when the value should stay the same after creation, but is determined at runtime.
Common examples:
- timestamps like
CreatedAt - IDs passed into constructors
- file paths built from environment settings
- dependency objects assigned once
- configuration loaded at startup
Example:
public class ConnectionInfo
{
public readonly string ConnectionString;
public ConnectionInfo(string connectionString)
{
ConnectionString = connectionString;
}
}
When static readonly is useful
Use static readonly for one shared value initialized at runtime.
Examples:
- default folders
- regex instances
- values loaded from configuration once
- reusable empty objects or predefined instances
Real Codebase Usage
In real C# codebases, developers often follow these patterns:
1. const for true constants only
public class ErrorCodes
{
public const string InvalidInput = "INVALID_INPUT";
}
This is common for:
- hardcoded error codes
- fixed names
- small immutable primitive values
2. readonly for object state that should not change
public class Order
{
public readonly Guid Id;
public Order(Guid id)
{
Id = id;
}
}
This protects object state after construction.
3. static readonly for shared runtime-initialized values
public class Defaults
{
public static readonly DateTime AppStartedAt = DateTime.Now;
}
4. Validation in constructors before assigning readonly
public class Customer
{
public readonly string Email;
public Customer(string email)
{
if (string.IsNullOrWhiteSpace(email))
throw new ArgumentException("Email is required.");
Email = email;
}
}
This is a common pattern: validate first, assign once, and keep the object safe afterward.
5. Avoiding const across assembly boundaries when values may change
If a library exposes a const and another project compiles against it, that constant value can be copied into the consuming assembly at compile time. If the library later changes the constant, the consuming project may still use the old value until it is recompiled.
Because of that, developers often prefer public static readonly for values that might change in a future version.
Common Mistakes
1. Trying to use runtime values in a const
Broken code:
public class Example
{
public const DateTime Start = DateTime.Now;
}
Why it fails:
DateTime.Nowis not a compile-time constant.
Fix:
public class Example
{
public static readonly DateTime Start = DateTime.Now;
}
2. Forgetting that const is implicitly static
Broken assumption:
public class Product
{
public const int TaxRate = 20;
}
You do not get a separate TaxRate for each object. There is only one value for the type.
3. Thinking readonly makes an object fully immutable
public class Example
{
public readonly List<string> Names = new List<string>();
}
The field cannot point to a different list later, but the list contents can still change:
var e = new Example();
e.Names.Add("Alice");
So readonly protects the reference, not necessarily the internal state of the object.
4. Trying to assign a readonly field outside a constructor
Broken code:
public class User
{
public readonly string Name;
public void SetName(string name)
{
Name = name;
}
}
Why it fails:
readonlyfields can only be assigned at declaration or in a constructor.
5. Using const for values that may change later
For example, a public API version or configurable file path may seem constant today, but if it changes in the future, using const can create versioning problems. In such cases, static readonly is often safer.
Comparisons
| Feature | const | readonly | static readonly |
|---|---|---|---|
| Assigned when | Compile time | Construction time | Type initialization/runtime |
| Must be known at compile time | Yes | No | No |
| Can vary per instance | No | Yes | No |
| Implicitly static | Yes | No | Yes, because you declare it static |
| Can be assigned in constructor | No | Yes | No instance constructor |
| Good for primitive fixed values | Yes | Sometimes | Sometimes |
| Good for runtime-computed values | No | Yes | Yes |
| Safer for public library values that may change | Usually no | Sometimes | Yes |
Quick decision guide
- Use
constwhen the value is truly permanent and known at compile time. - Use
readonlywhen each object gets its own fixed value during construction. - Use
static readonlywhen the class should have one shared fixed value determined at runtime.
Cheat Sheet
Quick rules
const= compile-time constantreadonly= assign once at declaration or in constructorstatic readonly= one shared runtime-initialized value
Syntax
public const int Max = 10;
public readonly int Id;
public static readonly string BasePath = AppDomain.CurrentDomain.BaseDirectory;
Use const when
- value is known at compile time
- value will never change
- value is a true constant like
7,404, or"GET"
Use readonly when
- value is known only at runtime
- value should not change after object creation
- value may be different for each instance
Important notes
constis implicitlystaticreadonlyis not automatically staticreadonlyfields can be assigned in constructorsconstvalues are copied into consuming assemblies at compile timereadonlyon a reference type does not make the object itself immutable
Common examples
public const int SecondsPerMinute = 60;
public readonly Guid OrderId;
public static readonly DateTime StartedAt = DateTime.Now;
FAQ
Can const be used with DateTime in C#?
No. DateTime values like DateTime.Now are not compile-time constants. Use readonly or static readonly instead.
Is const always static in C#?
Yes. A const field is implicitly static, so it belongs to the type, not to individual objects.
Can a readonly field be different for each object?
Yes. Because it can be assigned in the constructor, each instance can receive a different value.
Which is faster: const or readonly?
In most application code, the performance difference is not important. Choose based on meaning and correctness, not micro-optimization.
Should I use const for public values in a shared library?
Usually only if the value will never change. Otherwise public static readonly is often safer because of compile-time inlining of const values.
Does readonly make a list immutable?
No. It prevents reassigning the field reference, but the list contents can still be modified unless you use an immutable collection or read-only wrapper.
Mini Project
Description
Build a small C# class that models application settings and demonstrates when to use const, readonly, and static readonly. This project is useful because these three patterns appear often in real applications: fixed protocol values, per-object values set during construction, and shared values computed at startup.
Goal
Create a class design that correctly uses const for compile-time constants, readonly for per-instance immutable data, and static readonly for shared runtime values.
Requirements
- Create one
constfield for a truly fixed value. - Create one
readonlyfield that is assigned through the constructor. - Create one
static readonlyfield initialized from a runtime expression. - Instantiate at least two objects and show how their readonly values can differ.
- Print all values to the console.
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.