Menu
Coddy logo textTech

'readonly' & 'const' Keywords

Part of the Object Oriented Programming section of Coddy's C# journey — lesson 16 of 70.

C# provides two keywords for creating values that cannot change: const and readonly. While both prevent modification, they work differently and serve distinct purposes.

A const field must be assigned at declaration and its value is determined at compile time. It's implicitly static, meaning it belongs to the class rather than instances:

public class GameSettings
{
    public const int MaxPlayers = 4;
    public const double Gravity = 9.81;
}

You access constants through the class name: GameSettings.MaxPlayers. Constants work only with primitive types, strings, and null because the compiler must know the exact value.

A readonly field can be assigned at declaration or in a constructor, and its value is determined at runtime:

public class Player
{
    public readonly string Id;
    public readonly DateTime CreatedAt = DateTime.Now;
    
    public Player(string id)
    {
        Id = id;
    }
}

Unlike const, readonly fields can hold any type and can have different values per instance. Once the constructor finishes, the value cannot change.

Use const for values that are truly universal and will never change, like mathematical constants. Use readonly for values that should be set once but might vary between objects or need runtime calculation.

challenge icon

Challenge

Easy

Let's build a physics simulation configuration system that demonstrates when to use const for universal constants versus readonly for values that are set once at runtime.

You'll create two files to organize your code:

  • PhysicsConstants.cs: Define a PhysicsConstants class in the Simulation namespace. This class should contain universal constants that never change and are the same everywhere:
    • A const field Gravity set to 9.81
    • A const field SpeedOfLight set to 299792458
    • A const string GravityUnit set to "m/s^2"
  • Projectile.cs: Define a Projectile class in the Simulation namespace. Each projectile has values that should be set once when created and never modified afterward:
    • A readonly field Name (string)
    • A readonly field InitialVelocity (double)
    • A readonly field LaunchAngle (double, in degrees)
    • A constructor that accepts and sets all three values
    • A method GetMaxHeight() that calculates the maximum height using the formula: (velocity^2 * sin^2(angle)) / (2 * gravity). Use Math.Sin() and convert degrees to radians by multiplying by Math.PI / 180
  • Program.cs: In your main file, create a projectile using input values and display the physics constants along with the projectile's calculated maximum height.

You will receive three inputs:

  • Projectile name
  • Initial velocity (in m/s)
  • Launch angle (in degrees)

Print the output in this format:

Gravity: {Gravity} {GravityUnit}
Speed of Light: {SpeedOfLight} m/s
Projectile: {Name}
Initial Velocity: {InitialVelocity} m/s
Launch Angle: {LaunchAngle} degrees
Max Height: {maxHeight} m

Round the max height to 2 decimal places using Math.Round(value, 2).

For example, if the inputs are Rocket, 50, and 45, the output should be:

Gravity: 9.81 m/s^2
Speed of Light: 299792458 m/s
Projectile: Rocket
Initial Velocity: 50 m/s
Launch Angle: 45 degrees
Max Height: 63.71 m

Cheat sheet

C# provides two keywords for creating immutable values: const and readonly.

A const field must be assigned at declaration, is determined at compile time, and is implicitly static:

public class GameSettings
{
    public const int MaxPlayers = 4;
    public const double Gravity = 9.81;
}

Access constants through the class name: GameSettings.MaxPlayers. Constants work only with primitive types, strings, and null.

A readonly field can be assigned at declaration or in a constructor, and its value is determined at runtime:

public class Player
{
    public readonly string Id;
    public readonly DateTime CreatedAt = DateTime.Now;
    
    public Player(string id)
    {
        Id = id;
    }
}

readonly fields can hold any type and can have different values per instance. Once the constructor finishes, the value cannot change.

Use const for universal values that will never change. Use readonly for values that should be set once but might vary between objects or need runtime calculation.

Try it yourself

using System;
using Simulation;

class Program
{
    public static void Main(string[] args)
    {
        // Read inputs
        string name = Console.ReadLine();
        double velocity = Convert.ToDouble(Console.ReadLine());
        double angle = Convert.ToDouble(Console.ReadLine());

        // TODO: Create a Projectile object with the input values

        // TODO: Print the physics constants (Gravity with unit, Speed of Light)

        // TODO: Print the projectile information (Name, Initial Velocity, Launch Angle)

        // TODO: Calculate and print the max height (rounded to 2 decimal places)
    }
}
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Object Oriented Programming