const声明的常量为编译时常量,就是在编译器编译程序时就能够确定值,此后不能改变常量的值
readonly声明的常量为运行时常量,就是在运行时确定值,此后不能改变常量的值
声明方式不同:
1:运行时常量只能定义在类或结构体范围中,编译时常量还可以定义在方法中。
2:运行时常量可以是任何类型,编译时常量只能是基本类型(比如 int long等内建整性或浮点型,enum,string)。
3:编译时常量只能在初始化的时候赋值,运行时变量还可以在构造函数中赋值。
4:不能用new操作符来初始化一个编译时常量,即便它的类型是值类型。(这一点有问题,如代码中演示,可以编译通过)
最重要的区别:
编译时的常量性能比较好,而运行时常量灵活性比较好,原因是因为编译时常量在编译的时候会被它代表的值代替,运行时常量值是在运行时才被实际赋值。
如果在类的实例中使用readonly值,你可以为一个类的每一个实例设置不同的数据值。而如果用编译时常量,只能通过定义静态常量。
使用规则:
当值必须在编译时确定的时候你只能使用const:如属性参数和枚举类型(enum)定义。那些在不同发布版本间定义的值不会发生改变的,也可以用const定义。
除此之外,最好还是使用增加灵活性的readonly常量吧。
附上代码演示:
// 如果在类的实例中使用readonly值,你可以为一个类的每一个实例设置不同的数据值。而如果用编译时常量,只能通过定义静态常量。 // 运行时常量可以是任何类型, 编译时常量只能是基本类型 public class Person { readonly int id = 0; readonly DateTime birthDate = DateTime.Now; //birthDate不能声明为const public Person(int id, DateTime birthDate) { this.id = id; this.birthDate = birthDate; } public override string ToString() { return string.Format("Id:{0},BirthDate:{1}", id, birthDate.ToString("yyyy年MM月dd日")); } //只可以在构造函数中修改或者在声明的时候赋值 //public void ChangeId(int id) //{ // this.id = id; //} }
public class People { public const int Age = 10; //不可以在构造函数中修改编译时常量 //public People(int age) //{ // Age = age; //} //public void ChangeAge(int age) //{ // Age = age; //} public void Test() { //可以声明在方法中 const string Message = "Is a message"; const int year = new Int32(); Console.WriteLine(Message); if (Age <= 10) //编译时常量在编译的时候会被它代表的值代替,即Age会被10代替 { Console.WriteLine("真年轻哇"); } } public override string ToString() { return string.Format("Age:{0}",Age); } }