C# 常量

`const`、`readonly`、`static readonly`、以及它们的编译期内联行为。

Beginner
Key Points`const` 在编译期就替换成字面量;`readonly` 在运行时确定,但之后不能改。

const

C#
const double Pi = 3.14159;
const string AppName = "MyApp";
const int MaxRetry = 3;

// const 可以是编译期表达式
const int Timeout = 60 * 1000;

Console.WriteLine($"{AppName} {Pi} {MaxRetry} {Timeout}");
Output
MyApp 3.14159 3 60000

const values must be computable at compile time: numbers, strings, booleans, null references. No new, no method calls, no config reads.

readonly

C#
class Config
{
    public readonly DateTime CreatedAt;
    public readonly List<string> Tags = new();

    public Config()
    {
        CreatedAt = DateTime.Now;       // 只能在构造函数里赋值
        Tags.Add("默认");                // 集合内容仍可改
    }

    public void TryChange()
    {
        // CreatedAt = DateTime.Now;     // 编译错误:只读
        Tags.Add("新增");                // 可以,改的是内容不是引用
    }
}

var c = new Config();
c.TryChange();
Console.WriteLine(c.Tags.Count);
Output
2

readonly locks the reference, not the contents. Tags cannot point elsewhere but Add is fine. For truly immutable contents use IReadOnlyList<T> or immutable collections.

static readonly

C#
class App
{
    public static readonly string Version;
    public static readonly int[] AllowedPorts = { 80, 443, 8080 };

    static App()
    {
        Version = "1.0." + DateTime.Now.Year;
    }
}

Console.WriteLine(App.Version);
Console.WriteLine(App.AllowedPorts.Length);
Output
1.0.2026
3

三者对比

ModifierSet whenWhere assignableInlined
const编译期声明处是
readonly运行期声明处 / 构造函数否
static readonly运行期声明处 / 静态构造函数否
**Avoid const across assemblies.** Its value is inlined into consumers; change the source assembly without rebuilding them and they keep the old value — a nasty bug. Use static readonly for public constants.

字面量后缀

C#
var i = 42;              // int
var l = 42L;             // long
var f = 3.14f;           // float
var d = 3.14;            // double
var m = 3.14m;           // decimal
var u = 42u;             // uint
var hex = 0xFF;          // 255
var bin = 0b1010;        // 10
var sep = 1_000_000;     // 1000000,下划线只为可读

Console.WriteLine($"{i} {l} {f} {d} {m} {u} {hex} {bin} {sep}");
Output
42 42 3.14 3.14 3.14 42 255 10 1000000

3.14 is a double by default; float needs f and decimal needs m. A missing suffix is one of the most common C# compile errors.

Friends & Partners