程序设计过程中经常会用到常量,C# 语言中有 readonly, const 定义常量,如何准确的定义常量,它们的区别又是什么?
在了解这两个关键字之前,我们先来了解一下静态常量和动态常量。
使用 const 关键字来声明某个常量字段或常量局部变量,是静态常量。 常量字段和常量局部变量不能含变量并且不能修改。 常量可以为数字、布尔值、字符串或 null 引用。 不要创建常量来表示你需要随时更改的信息。
const 和 static 不能一起使用,因为常量字段是隐式静态的,const 编译之后就是 static 静态字段。

不能用 new 关键字初始化一个静态常量,即便是对一个值类型来说

const 常量不能是变量

类直接访问 const 常量。
namespace ConsoleApp1
{
class SampleClass
{
public int x;
public int y;
public const int C1 = 5;
public const int C2 = C1 + 5;
public SampleClass(int p1, int p2)
{
x = p1;
y = p2;
}
}
public class TestConst
{
public static void Main(string[] args)
{
var mC = new SampleClass(11, 22);
Console.WriteLine($"x = {mC.x}, y = {mC.y}");
Console.WriteLine($"C1 = {SampleClass.C1}, C2 = {SampleClass.C2}");
}
}
}
/* Output
x = 11, y = 22
C1 = 5, C2 = 10
*/
readonly 只能在声明期间或在同一个类的构造函数中向字段赋值。 可以在字段声明和构造函数中多次分配和重新分配只读字段,属于动态常量。
static readonly 静态只读字段,只读字段不是隐式静态的,所以要在类级别公开,就必须显式使用 static 关键字。
构造函数退出后,不能分配 readonly 字段。 此规则对于值类型和引用类型具有不同的含义:

namespace ConsoleApp1
{
class SamplePoint
{
public int x;
// Initialize a readonly field
public readonly int y = 25;
public readonly int z;
public static readonly string LAGUAGE = "C#";
public SamplePoint()
{
// Initialize a readonly instance field
z = 24;
}
public SamplePoint(int p1, int p2, int p3)
{
x = p1;
y = p2;
z = p3;
}
}
public class TestConst
{
public static void Main(string[] args)
{
Console.WriteLine($"SamplePoint.LAGUAGE = {SamplePoint.LAGUAGE}");
SamplePoint p1 = new SamplePoint(11, 21, 32); // OK
Console.WriteLine($"p1: x={p1.x}, y={p1.y}, z={p1.z}");
SamplePoint p2 = new SamplePoint();
p2.x = 55; // OK
//p2.y = 66;// Error
Console.WriteLine($"p2: x={p2.x}, y={p2.y}, z={p2.z}");
}
}
}
/* output
SamplePoint.LAGUAGE = C#
p1: x=11, y=21, z=32
p2: x=55, y=25, z=24
*/
readonly 表示只读,动态常量,运行时确定值,const 表示静态常量,编译时就确定值。const 常量,值一旦申明就不会发生变化,而人的年龄 age 可以定义成 readonly, 可以在构造函数中根据出生日期计算年龄。readonly 只能修饰 field,不能修饰 local variable,const 可修饰 field 和 local variable。
const 只能修饰 primitive type(数字、布尔值,字符) 以及很特殊的引用类型 string 和 null(string是不可变字符串,每次修改,都相当于重新创建了一个),为什么不能修饰其他的引用类型,因为其他的引用类型在编译期不能知道他们的确切值。不能用 new 关键字初始化一个静态常量。readonly 可以是任意数据类型,可以用 new 关键字初始化一个动态常量。const 变量默认是 static 类变量,不能加 static 修饰,readonly 默认不是,需要特意加上 static 才能变成类变量。const 只能在申明时赋值,不能外部赋值,readonly 可以外部赋值,但只能通过构造函数赋值。const 修饰的常量注重的是效率;readonly 修饰的常量注重灵活。const 修饰的常量没有内存消耗;readonly 因为需要保存常量,所以有内存消耗。