Skip to main content

How to Resolve Error "CS0191: A readonly field cannot be assigned to" in C#

The Compiler Error CS0191 is an immutability violation error. The message reads: "A readonly field cannot be assigned to (except in a constructor or init-only setter of the type in which the field is defined or a variable initializer)".

In C#, the readonly keyword indicates that a field can only be assigned a value during the initialization phase of the object. Once the constructor finishes executing, that field becomes permanently "read-only." Any attempt to change its value in a standard method, property setter, or external class triggers this error.

This guide explains the rules of readonly fields and how to fix assignment errors.

Understanding readonly Rules

A field marked readonly allows assignment only in these specific contexts:

  1. Variable Initializer: private readonly int _x = 10;
  2. Constructor: public MyClass() { _x = 10; }

If you try to assign a value anywhere else (like inside Update(), SetData(), or from another class), the compiler raises CS0191 to protect the data's integrity.

note

Difference from const:

  • const: Value must be known at compile-time.
  • readonly: Value is calculated at run-time, but can only be set once during object creation.

Scenario 1: Assigning in a Standard Method

This is the most common mistake. You define a field as readonly thinking "I don't want outside classes to touch this," but then you try to change it yourself inside a helper method.

Example of error:

public class Player
{
// Defined as readonly
public readonly int Score;

public Player()
{
Score = 0; // ✅ Valid: Inside Constructor
}

public void AddPoints(int points)
{
// ⛔️ Error CS0191: A readonly field cannot be assigned to...
// You cannot modify 'Score' after the constructor has finished.
Score = Score + points;
}
}

Solution 1: Remove the readonly Modifier

If the logic of your application requires the value to change over time (mutable state), then the field simply should not be readonly.

Solution: remove the keyword to allow modification at any time.

public class Player
{
// ✅ Correct: Removed 'readonly'. The field is now mutable.
public int Score;

public void AddPoints(int points)
{
// Now valid
Score = Score + points;
}
}

Solution 2: Move Assignment to Constructor

If the value is meant to be immutable (constant for the life of the object), but you tried to initialize it in an Init() or Setup() method, you must move that logic into the Constructor.

Example of error

public class Configuration
{
public readonly string Path;

// This method is called after the object is created
public void Initialize(string path)
{
// ⛔️ Error CS0191: Too late to assign readonly field.
Path = path;
}
}

Solution

public class Configuration
{
public readonly string Path;

// ✅ Correct: Assign inside the constructor.
public Configuration(string path)
{
Path = path;
}
}

Solution 3: Use Properties (private set or init)

Direct public fields are generally discouraged in C#. Using Properties gives you finer control over who can change the value and when.

Option A: private set (Internal Mutability)

Use this if you want the value to be read-only to the outside world, but changeable by the class itself methods.

public class Player
{
// Public Read, Private Write
public int Score { get; private set; }

public void AddPoints(int points)
{
// ✅ Correct: The class itself can use the private setter.
Score += points;
}
}

Option B: init (Immutability)

Available in C# 9.0+, init properties behave like readonly fields but allow for cleaner Object Initializer syntax.

public class Player
{
// Can be set in Constructor OR Object Initializer
public int Score { get; init; }
}

public class Program
{
void Main()
{
// ✅ Valid usage via Object Initializer
var p = new Player { Score = 100 };

// ⛔️ Error CS8852 (Similar to CS0191): Cannot change it later
// p.Score = 200;
}
}

Conclusion

CS0191 ensures that data you marked as "permanent" stays permanent.

  • Check Intent: Does this value need to change after the object is created?
    • Yes: Remove readonly. Use a property with private set if you want to restrict external access.
    • No: Ensure the assignment happens strictly inside the Constructor or variable declaration line.