Skip to content

C# - Constants

In C#, a literal is a fixed value that appears directly in your code (e.g., 101, 3.14, "Hello"). A constant is a variable whose value cannot be changed after it is defined. Constants are essential for creating readable, maintainable, and error-free code by giving meaningful names to fixed values.

C# provides two keywords to declare constants: const and readonly. It’s crucial to understand their differences.

Integer literals can be decimal (base 10), hexadecimal (base 16, with a 0x prefix), or binary (base 2, with a 0b prefix). You can use suffixes like U (unsigned), L (long), and UL (unsigned long) to specify the type.

int decimalLiteral = 42;
long longLiteral = 42L;
// Hexadecimal (255 in decimal)
int hexLiteral = 0xFF;
// Binary (10 in decimal) - C# 7.0+
int binaryLiteral = 0b1010;
// Digit separator for readability - C# 7.0+
long bigNumber = 1_000_000_000L;

These represent real numbers. Use the f suffix for float, d for double (optional, as it’s the default), and m for decimal (for high-precision financial calculations).

float piFloat = 3.14159f;
double piDouble = 3.1415926535;
decimal price = 29.99m;

Character literals are enclosed in single quotes ('a'). String literals are in double quotes ("Hello"). C# offers several powerful ways to define strings:

// Standard string with an escape sequence for newline
string standard = "Hello,\nWorld!";
// Verbatim string: ignores escape sequences, useful for file paths
string path = @"C:\Users\Guest\Documents";
// Interpolated string (C# 6.0+): embed expressions directly
var name = "Alice";
string greeting = $"Hello, {name}!"; // Output: Hello, Alice!
// Raw string literals (C# 11+): for multi-line strings or text containing quotes
string json = """
{
"name": "Bob",
"age": 30
}
""";

This is a frequent point of confusion for beginners. Here’s a clear distinction:

Featureconstreadonly
InitializationMust be initialized at declaration.Can be initialized at declaration or in a constructor.
Value TimeValue is set at compile-time.Value is set at run-time.
Type SupportOnly for built-in types (numeric, bool, string, enum) and null.Can be used with any data type, including custom classes.
ContextImplicitly static. Belongs to the class, not an instance.Can be either static (one value for the class) or instance-level (one value per object).

Use const for true, universal constants that will never, ever change, like mathematical values.

using System;
public class CircleCalculator
{
// A compile-time constant, accessible via the class name
public const double Pi = 3.14159;
public static void Main()
{
Console.Write("Enter Radius: ");
// Use TryParse for safe input handling
if (double.TryParse(Console.ReadLine(), out double radius) && radius > 0)
{
double area = CircleCalculator.Pi * radius * radius;
Console.WriteLine($"A circle with radius {radius} has an area of {area:F2}.");
}
else
{
Console.WriteLine("Invalid input. Please enter a positive number.");
}
}
}

Use readonly for values that are fixed for the lifetime of an object but might be different for each object instance.

using System;
public class User
{
// This value is set by the constructor and cannot be changed afterward.
public readonly Guid UserId;
public readonly DateTime CreationTime;
public string Username { get; set; }
public User(string username)
{
// readonly fields can be assigned here, in the constructor.
UserId = Guid.NewGuid();
CreationTime = DateTime.UtcNow;
Username = username;
}
public void DisplayInfo()
{
Console.WriteLine($"User '{Username}' created on {CreationTime:yyyy-MM-dd} with ID: {UserId}");
}
}
public class Program
{
public static void Main()
{
var user1 = new User("jdoe");
user1.DisplayInfo();
// The following line would cause a compile error:
// user1.CreationTime = DateTime.Now; // Error: A readonly field cannot be assigned to (except in a constructor)
}
}
  • Avoid “Magic Numbers/Strings”: Replace unnamed literals in your code with named constants. if (userRole == 5) is unclear, but if (userRole == UserRoles.Administrator) is self-documenting.
  • Configuration: Use static readonly fields to hold application configuration values loaded from a file at startup.
  • const for Performance: Since const values are embedded directly into the compiled code (IL), accessing them can be slightly faster, but this is a micro-optimization that is rarely significant.
  • readonly for Flexibility: readonly is more flexible and is often the better choice unless you have a true compile-time constant.