七、常量与字段(Constants and Fields)

CLR

第七章:常量与字段(Constants and Fields

1. 常量(Constants)

特点

  • 编译时确定:值在编译期确定,不能修改。
  • 隐式 static:常量自动是 static,无需显式声明 static
  • 存储方式:值被直接嵌入到使用它的代码中,而不是在运行时读取。

示例

public sealed class SomeLibraryType {
    public const int MaxEntries = 50;  // ✅ 编译期常量
}

IL 代码

IL_0006: ldc.i4.s 50  // 常量值直接嵌入

⚠️ 版本问题

如果引用常量的程序集不重新编译,更新 MaxEntries = 1000 不会影响旧的程序
解决方案:使用 static readonly 代替 const(见下方)。


2. 只读字段(Readonly Fields)

特点

  • 运行时确定:可以在 构造函数中初始化可利用反射来修改)。
  • 可以是任何类型const 只能是基本类型)。
  • 存储方式:值存储在内存中,而不是直接嵌入代码。

⚠️当某个字段是引用类型,并且该字段标记为readonly时,不可改变的是引用,而非字段引用的对象!

示例

public sealed class SomeLibraryType {
    public static readonly int MaxEntries = 50;  // ✅ 运行时常量
}

优点

  • 可跨程序集更新:更改 MaxEntries = 1000,无需重新编译依赖程序集。
  • 可存储复杂对象,如 DateTime.Now

3. 字段(Fields)

字段的 4 种类型

修饰符 特点 示例
static 静态字段,属于类,而非实例 public static int Count;
readonly 只读字段,只能在构造函数初始化 public readonly int ID;
volatile 防止编译器优化,用于多线程 public volatile int status;
普通字段 每个实例独立的存储 public int age;

示例

public class Example {
    public static int StaticField;  // 所有对象共享
    public readonly int ReadonlyField;  // 仅构造函数赋值
    public volatile int VolatileField;  // 线程安全
}

4. readonly vs const vs static readonly

特性 const readonly static readonly
赋值时机 编译时 运行时(构造函数) 运行时(静态构造函数)
是否 static 隐式 static 实例字段 静态字段
是否可变 不可变 构造后不可变 构造后不可变
适用场景 编译期常量 构造时确定的值 全局常量

5. Mermaid 图示

graph TD A["const"] -->|编译时确定| B["直接嵌入代码"] C["readonly"] -->|运行时确定| D["只能在构造函数中赋值"] E["static readonly"] -->|静态构造时赋值| F["跨程序集可修改"]

6. 面试题 & 解析

1️⃣ constreadonly 的区别?

解析

  • const 在编译期确定,不能更改。
  • readonly 在运行时确定,可在构造函数中赋值。
  • 推荐 readonly 代替 const 以避免版本问题

2️⃣ readonlystatic readonly 的区别?

解析

  • readonly 属于实例,每个对象可以有不同的值。
  • static readonly 属于类,所有对象共享同一值

🔹 示例

public class Example {
    public readonly int InstanceID;  // 每个对象不同
    public static readonly int GlobalID = 100;  // 所有对象相同
}

3️⃣ volatile 关键字的作用?

解析

  • 防止编译器优化,保证不同线程访问变量时数据一致性。
  • 适用于 多线程共享的变量,如 bool isRunning;

🔹 示例

public class Worker {
    private volatile bool _running = true;

    public void Stop() {
        _running = false;  // ✅ 确保线程读取到最新值
    }
}

4️⃣ const 是否支持复杂对象?

解析

  • const 仅支持基本类型 (int, string 等)
  • 复杂对象(如 DateTime)必须用 static readonly

🔹 示例

public class Constants {
    public const int Number = 10;  // ✅ 允许
    public static readonly DateTime StartTime = DateTime.Now;  // ✅ 允许
    // public const DateTime Invalid = DateTime.Now;  // ❌ 错误
}

5️⃣ const 是否可以在运行时修改?

解析

  • const 不能在运行时修改,只能在编译期赋值
  • 如需运行时修改,请使用 readonlystatic readonly

7. 总结

概念 核心考点
常量 (const) 编译时确定,值直接嵌入代码
只读字段 (readonly) 运行时确定,可在构造函数赋值
静态只读 (static readonly) 跨程序集可修改,存储在类级别
volatile 关键字 防止线程优化,保证多线程可见性
推荐使用 readonly 代替 const 避免跨程序集更新问题
posted @ 2025-08-26 10:06  世纪末の魔术师  阅读(5)  评论(0)    收藏  举报