C#中的Const vs Readonly:区别何在及何时使用?
\n\n每位C#开发者迟早都会面临一个两难选择:将值声明为const还是readonly?乍一看,这两个关键字做的是同一件事——禁止变量在初始化后被修改。但深入挖掘后,你会发现它们之间存在巨大差异,这些差异会影响代码的架构、性能甚至安全性。
在本文中,我们不仅会罗列文档中的干巴巴的事实。我们将分析真实场景,揭示潜在陷阱,并帮助您做出明智的选择。开始吧!
\n\nC#中的const是什么?
\n\nConst 是一个编译时常量。它的值必须在编译时已知,并且在运行时不能更改。
\n\n- \n
- 只能是原始类型:
int、double、string、bool、enum和null。 \n - 隐式为
static——属于类型,而非实例。 \n - 值在编译阶段直接嵌入到代码中(类似于C++中的宏)。 \n
- 不能与
new或引用类型一起使用(string除外)。 \n
public class MathConstants\n{\n public const double Pi = 3.14159;\n public const int MaxRetries = 5;\n public const string AppName = "MyApp";\n \n // 错误!引用类型(除了string)不能使用\n // public const List<int> Numbers = new List<int>();\n}\n\n当编译器遇到const时,它会将值内联到IL代码中。这意味着,如果你从另一个程序集中使用一个常量,然后更改了它的值,旧的程序集仍将使用旧值——直到它们被重新编译。
C#中的readonly是什么?
\n\nReadonly 是一个字段,只能在声明时或类的构造函数中初始化。之后就不能再修改它。
\n\n- \n
- 可以是任何类型:值类型或引用类型。 \n
- 可以是静态的,也可以是实例的。 \n
- 值在运行时计算(例如,可以使用
new或调用方法)。 \n - 不会嵌入到代码中——它是一个带有写保护的普通字段。 \n
public class Config\n{\n public readonly DateTime CreatedAt = DateTime.Now;\n public readonly List<string> Tags;\n public static readonly Guid InstanceId = Guid.NewGuid();\n \n public Config()\n {\n Tags = new List<string> { "csharp", "tutorial" };\n // 错误!不能在构造函数之后修改\n // Tags = new List<string>();\n }\n}\n\n一个重要细节:readonly只保护引用,而不保护对象的内容。如果你有一个readonly List<int>,你不能分配一个新的列表,但可以随意添加或删除元素。
const与readonly对比:差异表
\n\n为了巩固知识,这里有一个直观的对比:
\n\n| 标准 | \nconst | \nreadonly | \n
|---|---|---|
| 计算时间 | \n编译时 | \n执行时(运行时) | \n
| 数据类型 | \n仅原始类型 + string | \n任何类型 | \n
| 静态性 | \n隐式static | \n可以是static或instance | \n
| 可变性 | \n永远不可变 | \n仅在构造函数中可变 | \n
| 访问方式 | \n作为 | \n