C# 中 readonly 与 const 的使用
总目录
前言
在C#编程中,readonly 和 const 是两个用于定义不可变数据的关键字。它们都旨在创建那些一旦赋值后就不能再改变的字段或变量。尽管这两个关键字看起来相似,但它们有着不同的特性和适用场景。本文将深入探讨 readonly 和 const 的区别,并介绍如何根据具体需求选择合适的选项
一、const 关键字
1. 基本概念
const
用来声明编译时常量,即其值是在编译时确定并在程序运行期间不会改变的。这意味着 const 字段的值必须在声明时就赋予,并且该值在整个应用程序生命周期内都是固定的。
2. 语法示例
public class ConstantsExample
{
// 定义类级别的常量
public const double Pi = 3.14159265358979323846;
public const string AppName = "MyApplication";
public void DisplayConstants()
{
// 定义局部常量
const int MaxItems = 100;
// 使用常量
Console.WriteLine($"Pi: {Pi}, App Name: {AppName}, Max Items: {MaxItems}");
}
}
internal class Program
{
static void Main(string[] args)
{
// 使用常量
Console.WriteLine($"Pi: {ConstantsExample.Pi}, App Name: {ConstantsExample.AppName}");
}
}
3. 特性
- 必须初始化:在声明 const 常量时,必须同时为其赋值,否则会引发编译错误。
public const string ConstStr;//报错:CS0145:常量字段要求提供一个值
- 编译时求值:const 常量的值在编译时就被确定并替换到使用它的地方。这意味着,如果const常量的值发生变化,所有引用它的代码都需要重新编译。
- 如果在一个程序集中定义了 const,并在另一个程序集中使用它,当 const 的值发生变化时,必须重新编译所有依赖它的程序集,这是一个很隐蔽的问题。而 readonly 通常没有这个问题。
- const 效率高的原因是代码中引用 const 变量的地方,经过编译器编译后会直接使用 const 变量的实际值来代替,如:
const int constVal = 100;
Console.WriteLine(constVal);
编译后的 IL 代码实际上是:
Console.WriteLine(100);
- 数据类型限制:const 常量只能是以下类型:sbyte、byte、short、ushort、int、uint、long、ulong、char、float、double、decimal、bool、string,或者是枚举类型。
- 作用域:const 可以作为类成员、结构体成员或者局部变量(从C# 7.2开始),但不能作为实例成员。
二、readonly 关键字
1. 基本概念
readonly 也用来定义只读字段,其值可以在声明时或构造函数中初始化,初始化后便不能再更改。与const不同,readonly字段的值在运行时确定,这为我们提供了更大的灵活性。。
2. 语法示例
可以在声明时或构造函数中初始化
public class ReadonlyExample
{
// 声明只读字段
public readonly double CurrentVersion;
public readonly string CompanyName;
public ReadonlyExample(double version, string company)
{
// 在构造函数中初始化
CurrentVersion = version;
CompanyName = company;
}
}
3. 特性
- 初始化时机:readonly字段可以在声明时初始化,也可以在构造函数中初始化,但是只能初始化一次。这为对象的初始化提供了更多的灵活性。
- 运行时求值:readonly字段的值可以在运行时确定,这使得我们可以根据不同的运行时条件来初始化它。例如,从配置文件、数据库或其他外部源获取值。
- readonly 字段在运行时分配内存并进行访问,与普通字段类似。
- 数据类型限制:readonly字段可以是任何数据类型
- 作用域:readonly 可以作为静态成员或实例成员存在,提供更大的灵活性。
三、readonly 与 const 的区别
1. 初始化时间
- const 在编译时初始化,其值在编译期间就必须确定。
- readonly 可以在运行时初始化,既可以在声明时赋值,也可以在构造函数中赋值。
2. 内存分配
- const 常量在编译时会将其值嵌入到使用它的代码中,不会单独分配内存。
- readonly 字段在运行时为每个对象实例分配内存,即使多个对象实例的readonly字段值相同。
- const 天然就是静态的,不能为 const 常量添加 static 修饰符。readonly 则不然。
3. 数据类型限制
- const 只支持有限的数据类型,如基本数值类型、布尔类型、字符串类型和枚举类型。
- readonly 没有数据类型限制,可以用于任何数据类型。
4. 可变性
- const 的值在编译后就完全固定,无法在运行时更改。
- readonly 的值虽然不能在初始化后更改,但可以根据运行时的不同情况进行初始化。
四、适用场景
- 编译时已知值:如果您知道一个值在编译时就已经确定,并且永远不会改变,那么应该使用 const。数学常量与固定配置:如圆周率Pi、重力加速度G等数学常量,以及应用程序的固定配置参数,如数据库连接字符串的一部分(如果从不改变)。
- 运行时确定值:如果值需要在运行时计算或依赖于其他因素(如配置文件、用户输入),则应使用 readonly。此外,当您希望某个字段在对象创建后保持不变,但其值可能因不同对象而异时,readonly 是更好的选择。
- 性能考虑:由于 const 值会被直接嵌入到调用方的代码中,因此对于频繁使用的常量,它可能会导致更大的程序集大小。另一方面,readonly 字段会在运行时加载,这通常会更节省空间,但在第一次访问时会有轻微的性能开销。
- 可维护性:使用 const 有助于提高代码的可读性和自我描述能力,因为读者可以立即看到常量的值。然而,如果将来需要更改这个值,那么所有引用了该常量的地方都需要重新编译。相比之下,readonly 更易于维护,特别是在大型项目中。
结语
回到目录页:C#/.NET 知识汇总
希望以上内容可以帮助到大家,如文中有不对之处,还请批评指正。
参考资料:
使用 C# readonly 和 const 定义常量,高手不愿意告诉你的 10 个真相