Question

Const vs Readonly in C#: What's the Difference and When to Use Each

csharp.netconstantsreadonly

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 readonly if 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 const for true fixed values that will never change and are known at compile time.
  • Use readonly for 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 time
  • readonly = assigned once at initialization/runtime, then locked
Take Quiz

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:

  1. The compiler sees FixedValue and stores 10 as a compile-time constant.
  2. FixedValue belongs to the class itself, not to objects a or b.
  3. When new Example(5) runs, the constructor is called.
  4. Inside the constructor, InstanceValue is assigned 5.
  5. When new Example(9) runs, a new object is created.
  6. Its InstanceValue is assigned 9.

So the results are:

  • Example.FixedValue is always 10
  • a.InstanceValue is 5
  • b.InstanceValue is 9

This shows the key difference:

  • const is one fixed compile-time value
  • readonly can 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
Take Quiz

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.Now is 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:

  • readonly fields 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

Featureconstreadonlystatic readonly
Assigned whenCompile timeConstruction timeType initialization/runtime
Must be known at compile timeYesNoNo
Can vary per instanceNoYesNo
Implicitly staticYesNoYes, because you declare it static
Can be assigned in constructorNoYesNo instance constructor
Good for primitive fixed valuesYesSometimesSometimes
Good for runtime-computed valuesNoYesYes
Safer for public library values that may changeUsually noSometimesYes

Quick decision guide

  • Use const when the value is truly permanent and known at compile time.
  • Use readonly when each object gets its own fixed value during construction.
  • Use static readonly when the class should have one shared fixed value determined at runtime.
Take Quiz

Cheat Sheet

Quick rules

  • const = compile-time constant
  • readonly = assign once at declaration or in constructor
  • static 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

  • const is implicitly static
  • readonly is not automatically static
  • readonly fields can be assigned in constructors
  • const values are copied into consuming assemblies at compile time
  • readonly on 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.

Take Quiz

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 const field for a truly fixed value.
  • Create one readonly field that is assigned through the constructor.
  • Create one static readonly field initialized from a runtime expression.
  • Instantiate at least two objects and show how their readonly values can differ.
  • Print all values to the console.
Take Quiz

Keep learning

Related questions

View more