When to Use const vs readonly in C#
const fields are compile-time constants that must be initialized at declaration and cannot change. readonly fields are runtime constants that can be initialized at declaration or in the constructor.
Use const for true constants that will never change (mathematical constants, fixed configuration values). Use readonly for values that are constant per instance but may be set at runtime or differ between instances.
const values are embedded directly in the compiled code, while readonly values are stored in memory and evaluated at runtime. This makes const slightly faster but less flexible.
C# Example Code
using System;
public class MathConstants
{
// const - compile-time constant
// Must be primitive types or strings
public const double Pi = 3.14159265359;
public const int MaxRetries = 3;
public const string ApplicationName = "MyApp";
// readonly - runtime constant
// Can be any type, including complex objects
public readonly DateTime CreatedDate;
public readonly Guid InstanceId;
public readonly string ConnectionString;
// Static readonly - shared across all instances
public static readonly int MaxConnections = 100;
public static readonly TimeSpan Timeout = TimeSpan.FromSeconds(30);
public MathConstants(string environment)
{
// readonly can be set in constructor
CreatedDate = DateTime.Now;
InstanceId = Guid.NewGuid();
// Value can depend on parameters
ConnectionString = environment == "Production"
? "Server=prod;Database=app;"
: "Server=dev;Database=app;";
}
public void DemonstrateUsage()
{
// const can be used in constant expressions
const int bufferSize = MaxRetries * 1024; // Evaluated at compile time
Console.WriteLine($"Pi: {Pi}");
Console.WriteLine($"Max Retries: {MaxRetries}");
Console.WriteLine($"Buffer Size: {bufferSize}");
// readonly values are evaluated at runtime
Console.WriteLine($"Instance ID: {InstanceId}");
Console.WriteLine($"Created: {CreatedDate}");
Console.WriteLine($"Connection: {ConnectionString}");
// Cannot modify either
// Pi = 3.14; // Error: const cannot be modified
// InstanceId = Guid.NewGuid(); // Error: readonly cannot be modified
}
}
public class ConfigExample
{
// const - same for all instances, known at compile time
public const string Version = "1.0.0";
public const int DefaultPort = 8080;
// readonly - can differ per instance
public readonly string Environment;
public readonly int Port;
public ConfigExample(string environment, int? customPort = null)
{
Environment = environment;
// readonly can use logic
Port = customPort ?? DefaultPort;
}
}
Console.WriteLine("=== const examples ===");
Console.WriteLine($"Pi: {MathConstants.Pi}");
Console.WriteLine($"Max Retries: {MathConstants.MaxRetries}");
Console.WriteLine($"App Name: {MathConstants.ApplicationName}");
Console.WriteLine("\n=== readonly examples ===");
var math1 = new MathConstants("Development");
math1.DemonstrateUsage();
Console.WriteLine("\n=== Different readonly values per instance ===");
var config1 = new ConfigExample("Development");
var config2 = new ConfigExample("Production", 9000);
Console.WriteLine($"Config 1 - Env: {config1.Environment}, Port: {config1.Port}");
Console.WriteLine($"Config 2 - Env: {config2.Environment}, Port: {config2.Port}");
// const is shared across all - accessed via class name
Console.WriteLine($"\n=== const is the same everywhere ===");
Console.WriteLine($"Version: {ConfigExample.Version}");
// static readonly is also shared but evaluated at runtime
Console.WriteLine($"\n=== static readonly ===");
Console.WriteLine($"Max Connections: {MathConstants.MaxConnections}");
Console.WriteLine($"Timeout: {MathConstants.Timeout.TotalSeconds} seconds");
// Performance note
Console.WriteLine("\n=== Performance characteristics ===");
Console.WriteLine("const: Embedded in IL, slightly faster access");
Console.WriteLine("readonly: Stored in memory, more flexible");
// Versioning consideration
Console.WriteLine("\n=== Versioning note ===");
Console.WriteLine("const: If changed, all assemblies must be recompiled");
Console.WriteLine("readonly: If changed, only the defining assembly needs recompilation");