一般情况下,如果你需要声明的常量是普遍公认的并作为单个使用,例如圆周率,黄金分割比例等。你可以考虑使用C# const常量,如:public const double PI = 3.1415926;。如果你需要声明常量,不过这个常量会随着实际的运行情况而决定,那么,readonly常量将会是一个不错的选择,例如上面第一个例子的订单号Order.ID。
另外,如果要表示对象内部的默认值的话,而这类值通常是常量性质的,那么也可以考虑const。更多时候我们对源代码进行重构时(使用Replace Magic Number with Symbolic Constant),要去除魔数(Magic Number)的影响都会借助于const的这种特性。
对于readonly和const所修饰的变量究竟是属于类级别的还是实例对象级别的问题,我们先看看如下代码:
- using System;
- namespace ConstantLab
- {
- class Program
- {
- static void Main(string[] args)
- {
- Constant c = new Constant(3);
- Console.WriteLine("ConstInt = " + Constant.ConstInt.ToString());
- Console.WriteLine("ReadonlyInt = " + c.ReadonlyInt.ToString());
- Console.WriteLine("InstantReadonlyInt = " + c.InstantReadonlyInt.ToString());
- Console.WriteLine("StaticReadonlyInt = " + Constant.StaticReadonlyInt.ToString());
- Console.WriteLine("Press any key to continue");
- Console.ReadLine();
- }
- }
- class Constant
- {
- public Constant(int instantReadonlyInt)
- {
- InstantReadonlyInt = instantReadonlyInt;
- }
- public const int ConstInt = 0;
- public readonly int ReadonlyInt = 1;
- public readonly int InstantReadonlyInt;
- public static readonly int StaticReadonlyInt = 4;
- }
- }
使用Visual C#在 Main()里面使用IntelliSence插入Constant的相关field的时候,发现ReadonlyInt和 InstantReadonlyInt需要指定Constant的实例对象;而ConstInt和StaticReadonlyInt却要指定 Constant class(参见上面代码)。可见,用const或者static readonly修饰的常量是属于类级别的;而readonly修饰的,无论是直接通过赋值来初始化或者在实例构造函数里初始化,都属于实例对象级别。
一般情况下,如果你需要表达一组相关的编译时确定常量,你可以考虑使用枚举类型(enum),而不是把多个C# const常量直接嵌入到class中作为field,不过这两种方式没有绝对的孰优孰劣之分。
- using System;
- enum CustomerKind
- {
- SuperVip,
- Vip,
- Normal
- }
- class Customer
- {
- public Customer(string name, CustomerKind kind)
- {
- m_Name = name;
- m_Kind = kind;
- }
- private string m_Name;
- public string Name
- {
- get { return m_Name; }
- }
- private CustomerKind m_Kind;
- public CustomerKind Kind
- {
- get { return m_Kind; }
- }
- public override string ToString()
- {
- return "Name: " + m_Name + "[" + m_Kind.ToString() + "]";
- }
- }