C#中的静态常量(const)和动态常量(static和readonly)⽤法
和区别
C#中有两种常量类型,分别为readonly(运⾏时常量)与const(编译时常量),本⽂将就这两种类型的不同特性进⾏⽐较并说明各⾃的适⽤场景。
⼯作原理
readonly为运⾏时常量,程序运⾏时进⾏赋值,赋值完成后便⽆法更改,因此也有⼈称其为只读变量。
const为编译时常量,程序编译时将对常量值进⾏解析,并将所有常量引⽤替换为相应值。
下⾯声明两个常量:
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就可以正常编译:
1public readonly DateTime D = DateTime.MinValue;
可维护性
readonly以引⽤⽅式进⾏⼯作,某个常量更新后,所有引⽤该常量的地⽅均能得到更新后的值。
const的情况要稍稍复杂些,特别是跨程序集调⽤:
1public class Class1
2 {
3public static readonly int A = 2; //A为运⾏时常量
4public const int B = 3; //B为编译时常量
5 }
6
7public class Class2
8 {
9public static int C = Class1.A + Class1.B; //变量C的值为A、B之和
10 }
11
12 Console.WriteLine(Class2.C); //输出"5"
假设Class1与Class2位于两个不同的程序集,现在更改Class1中的常量值:
1public class Class1
2 {
3public static readonly int A = 4; //A为运⾏时常量
4public const int B = 5; //B为编译时常量
5 }
编译Class1并部署(注意:这时并没有重新编译Class2),再次查看变量C的值:
1 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常量。
C#中的static 和Java中的static
简单,两者⽤法完全是⼀致的。从两⽅⾯讨论:
1. 变量是属于类的,不是实例级别的。只能通过类名调⽤,不能通过实例调⽤。
2. 如果在定义时就赋值了,那么在类初始化的时候,最先完成所有静态变量的赋值。但是要注意,所有静态变量的初始化顺序是⽆法确定的。
C# 中的const 和Java中的finnal
很长⼀段时间我⼀直认为两者是相同的作⽤,⽆⾮是变量初始化后不能更改,即只能在定义时或者构造函数中赋值。然⽽这仅仅只是⽚⾯的,下⾯将为⼤家详细分析:
1.修饰变量
准确的说C#中的const 等价于 Java中的static final,也就是说,Java中final不具有static的功能。⽽C#中的const具有static的功能。因此在C#中 public static const string 等将于 public const string。
2.修饰类和⽅法
此时Java中的final类似C#中的sealed,就是说,final修饰的类不能被继承,final修饰的⽅法不能被覆盖。
⽽C#中的const不能修饰类和⽅法。
问题:
1. 私有静态成员的作⽤(private static 变量)
字⾯表⽰私有的,类外不能使⽤;静态的,全局变量。看上去很⽭盾,⼜不能被类外使⽤,要全局的
有什么⽤。问得好,类中全局也是很有意义的,例如 private static int a = 5,那么就可以保证变量a在类的初始化过程中将被优先初始化(在构造函数执⾏之前)。这样如果对象A 的初始化需要对象B的实例,那么就可以⽤这种申明,以保证在类A在构造函数中能够使⽤类B的实例。同时private⼜能够保证类B的实例只能在类A中使⽤,起到很好的密封作⽤。
2. 私有最终成员作⽤(private final 变量)
在类构造函数完成前必须对该成员完成初始化,⼀旦定义不许更改;该成员只能在本类中使⽤。实例,⼦类中都不能使⽤。
private static final修饰的成员在申明的时就被赋值,保证在构造函数中可以被使⽤,⼀个被private static final修饰的成员通常表⽰其他组件的⼀个实例,且变量是类中的全局变量。
private final 修饰的成员在构造中被赋值,表⽰它是该类全局的私有成员变量,且该类的构造需要传⼊他们的初始值,才能完成类的初始化。
C# const和static readonly区别
const: ⽤const修饰符声明的成员叫常量,是在编译期初始化并嵌⼊到客户端程序
static readonly: ⽤static readonly修饰符声明的成员依然是变量,只不过具有和常量类似的使⽤⽅法:通过类进⾏访问、初始化后不可以修
改。但与常量不同的是这种变量是在运⾏期初始化。
C# const和static readonly区别⽰例:
1using System;
2using System.Collections.Generic;
3using System.Text;
4
5namespace Example02Lib
6 {
7public class Class1
8 {
9public const String strConst = "Const";
10public static readonly String strStaticReadonly = "StaticReadonly";
11//public const String strConst = "Const Changed";
12//public static readonly String strStaticReadonly = "StaticReadonly Changed";
13 }
14 }
客户端代码:
1using System;
2using System.Collections.Generic;
3using System.Text;
4using Example02Lib;
5namespace Example02
6 {
7class Program
8 {
9static void Main(string[] args)
10 {
11//修改Example02中Class1的strConst初始值后,只编译Example02Lib项⽬
12//然后到资源管理器⾥把新编译的Example02Lib.dll拷贝所在的⽬录,执⾏ 13//切不可在IDE⾥直接调试运⾏因为这会重新编译整个解决⽅案!!
14//可以看到strConst的输出没有改变,⽽strStaticReadonly的输出已经改变
15//表明Const变量是在编译期初始化并嵌⼊到客户端程序,⽽StaticReadonly是在运⾏时初始化的
16 Console.WriteLine("strConst : {0}", Class1.strConst);
static修饰的变量17 Console.WriteLine("strStaticReadonly : {0}",
18 Class1.strStaticReadonly);
19 Console.ReadLine();
20 }
21 }
22 }
修改后的⽰例:
1using System;
2using System.Collections.Generic;
3using System.Text;
4
5namespace Example02Lib
6 {
7public class Class1
8 {
9//public const String strConst = "Const";
10//public static readonly String strStaticReadonly = "StaticReadonly";
11public const String strConst = "Const Changed";
12public static readonly String strStaticReadonly = "StaticReadonly Changed";
13 }
14 }
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论