两种常量类型-readonly和const

简介: C#中有两种常量类型,分别为readonly(运行时常量)与const(编译时常量),本文将就这两种类型的不同特性进行比较并说明各自的适用场景。 工作原理   readonly   为运行时常量(动态常量),程序运行时进行赋值,赋值完成后便无法更改,因此也有人称其为只读变量。

C#中有两种常量类型,分别为readonly(运行时常量)与const(编译时常量),本文将就这两种类型的不同特性进行比较并说明各自的适用场景。

工作原理

  readonly

  为运行时常量(动态常量),程序运行时进行赋值,赋值完成后便无法更改,因此也有人称其为只读变量。
  const

  为编译时常量(静态常量),程序编译时将对常量值进行解析,并将所有常量引用替换为相应值。 

  常量可以为数字、布尔值、字符串或 null 引用,不允许在常数声明中使用 static 修饰符,只能在该字段的声明中初始化。

区别可以从静态常量和动态常量的特性来说明:

  • const修饰的常量在声明时必须初始化值;readonly修饰的常量可以不初始化值,且可以延迟到构造函数。
  • cons修饰的常量在编译期间会被解析,并将常量的值替换成初始化的值;而readonly延迟到运行的时候。
  • const修饰的常量注重的是效率;readonly修饰的常量注重灵活。
  • const修饰的常量没有内存消耗;readonly因为需要保存常量,所以有内存消耗。
  • const只能修饰基元类型、枚举类、或者字符串类型;readonly却没有这个限制。

 

实例解说

下面声明两个常量:

  public static readonly int A = 2; //A为运行时常量
  public const int B = 3; //B为编译时常量

下面的表达式:

  int C = A + B;

经过编译后与下面的形式等价:

  int C = A + 3;

可以看到,其中的const常量B被替换成字面量3,而readonly常量A则保持引用方式。

声明及初始化

readonly常量只能声明为类字段,支持实例类型或静态类型,可以在声明的同时初始化或者在构造函数中进行初始化,初始化完成后便无法更改。
const常量除了可以声明为类字段之外,还可以声明为方法中的局部常量,默认为静态类型(无需用static修饰,否则将导致编译错误),但必须在声明的同时完成初始化。

数据类型支持

由于const常量在编译时将被替换为字面量,使得其取值类型受到了一定限制。const常量只能被赋予数字(整数、浮点数)、字符串以及枚举类型。下面的代码无法通过编译:

public const DateTime D = DateTime.MinValue;
改成readonly就可以正常编译:

public readonly DateTime D = DateTime.MinValue;

可维护性

readonly以引用方式进行工作,某个常量更新后,所有引用该常量的地方均能得到更新后的值。
const的情况要稍稍复杂些,特别是跨程序集调用:

public class Class1
{
public static readonly int A = 2; //A为运行时常量
public const int B = 3; //B为编译时常量
}

public class Class2
{
public static int C = Class1.A + Class1.B; //变量C的值为A、B之和
}

Console.WriteLine(Class2.C); //输出"5"
假设Class1与Class2位于两个不同的程序集,现在更改Class1中的常量值:

public class Class1
{
public static readonly int A = 4; //A为运行时常量
public const int B = 5; //B为编译时常量
}
编译Class1并部署(注意:这时并没有重新编译Class2),再次查看变量C的值:

Console.WriteLine(Class2.C); //输出"7"
结果可能有点出乎意料,让我们来仔细观察变量C的赋值表达式:

public static int C = Class1.A + Class1.B;
编译后与下面的形式等价:

 

public static int C = Class1.A + 3;
因此不管常量B的值如何变,对最终结果都不会产生影响。虽说重新编译Class2即可解决这个问题,但至少让我们看到了const可能带来的维护问题。

性能比较

const直接以字面量形式参与运算,性能要略高于readonly,但对于一般应用而言,这种性能上的差别可以说是微乎其微。

适用场景

在下面两种情况下:
a.取值永久不变(比如圆周率、一天包含的小时数、地球的半径等)
b.对程序性能要求非常苛刻
可以使用const常量,除此之外的其他情况都应该优先采用readonly常量。

 

参考:

http://www.cnblogs.com/liujie2272/p/5465255.html

http://www.cnblogs.com/royenhome/archive/2010/05/22/1741592.html

https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/keywords/readonly

 

相关文章
|
8月前
|
程序员 C语言 C++
35.【C/C++ 枚举(bool)类型和宏定义 (超详细)】(二)
35.【C/C++ 枚举(bool)类型和宏定义 (超详细)】
75 0
|
1月前
|
编译器 C++
|
1月前
|
JavaScript
const和readonly的区别
const和readonly的区别
|
7月前
|
编译器 C语言 C++
const修饰的究竟是常量还是变量?
const修饰的究竟是常量还是变量?
52 0
|
7月前
|
C++
Const Reference(常量引用)
Const Reference(常量引用)是 C++ 编程语言中的一种特殊类型,它允许将一个常量的引用传递给函数或赋值给其他变量。常量引用主要用于传递只读数据,防止在函数内部修改实参。 使用常量引用的步骤如下:
50 5
|
8月前
|
编译器 C语言 C++
35.【C/C++ 枚举(bool)类型和宏定义 (超详细)】(一)
35.【C/C++ 枚举(bool)类型和宏定义 (超详细)】
44 0
|
Dart
Dart之变量(var)、常量(const)
Dart之变量(var)、常量(const)
56 0
Dart之变量(var)、常量(const)
|
编译器 程序员 C++
尽可能使用const修饰符
尽可能使用const修饰符
113 0
|
C语言 C++ 安全
const类型变量的详细解读
const类型变量--------------------------------------int i;const int *p; --------------------------------------int i;int *const p = &i;--------------------------------------int i;const int *const p = &i; 三者有何区别呢?-------------------------------------- 指向常量的指针 和 指针常量 const int *p;  //定义一个指向常量的指针。
1136 0