



















C#引入了readonly修饰符来表示只读域,const来表示不变常量。顾名思义对只读域不能进行写操作,不变常量不能被修改,这两者到底有什么区别呢?只读域只能在初始化--声明初始化或构造器初始化--的过程中赋值,其他地方不能进行对只读域的赋值操作,否则编译器会报错。只读域可以是实例域也可以是静态域。只读域的类型可以是C#语言的任何类型。但const修饰的常量必须在声明的同时赋值,而且要求编译器能够在编译时期计算出这个确定的值。const修饰的常量为静态变量,不能够为对象所获取。const修饰的值的类型也有限制,它只能为下列类型之一(或能够转换为下列类型的):sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal, bool, string, enum类型, 或引用类型。值得注意的是这里的引用类型,由于除去string类型外,所有的类型出去null值以外在编译时期都不能由编译器计算出他们的确切的值,所以我们能够声明为const的引用类型只能为string或值为null的其他引用类型。显然当我们声明一个null的常量时,我们已经失去了声明的意义--这也可以说是C#设计的尴尬之处!
这就是说,当我们需要一个const的常量时,但它的类型又限制了它不能在编译时期被计算出确定的值来,我们可采取将之声明为static readonly来解决。但两者之间还是有一点细微的差别的。看下面的两个不同的文件:
//file1.cs //csc /t:library file1.cs using System; namespace MyNamespace1 { public class MyClass1 { public static readonly int myField = 10; } } //file2.cs //csc /r:file1.dll file2.cs using System; namespace MyNamespace2 { public class MyClass1 { public static void Main() { Console.WriteLine(MyNamespace1.MyClass1.myField); } } } 我们的两个类分属于两个文件file1.cs 和file2.cs,并分开编译。在文件file1.cs内的域myField声明为static readonly时,如果我们由于某种需要改变了myField的值为20,我们只需重新编译文件file1.cs为file1.dll,在执行file2.exe时我们会得到20。但如果我们将static readonly改变为const后,再改变myField的初始化值时,我们必须重新编译所有引用到file1.dll的文件,否则我们引用的MyNamespace1.MyClass1.myField将不会如我们所愿而改变。这在大的系统开发过程中尤其需要注意。实际上,如果我们能够理解const修饰的常量是在编译时便被计算出确定的值,并代换到引用该常量的每一个地方,而readonly时在运行时才确定的量--只是在初始化后我们不希望它的值再改变,我们便能理解C#设计者们的良苦用心,我们才能彻底把握const和readonly的行为!
---------------------
Features:
Examples:
Explaintion:
- 如果结合数据库使用,ID field通常都会都会与某个表的主健(primary key)关联起来,如Orders表的OrderID。
- 数据库的主健通常采用以下三种方式:
- 自动递增值。你可以通过把DataColumn.AutoIncrement设定为true值来激活自动递增特性。
- 唯一名称。这个是使用自己定义的算法来生成一个唯一序列号。
- GUID(全局唯一标识符)。你可以通过System.Guid结构来生成GUID,如上例。
Remarks:
Comments:
------------------------------------------------
我们都知道,const和static readonly的确很像:通过类名而不是对象名进行访问,在程序中只读等等。在多数情况下可以混用。
二者本质的区别在于,const的值是在编译期间确定的,因此只能在声明时通过常量表达式指定其值。而static readonly是在运行时计算出其值的,所以还可以通过静态构造函数来赋值。
明白了这个本质区别,我们就不难看出下面的语句中static readonly和const能否互换了:
1. static readonly MyClass myins = new MyClass();
2. static readonly MyClass myins = null;
3. static readonly A = B * 20;
static readonly B = 10;
4. static readonly int [] constIntArray = new int[] {1, 2, 3};
5. void SomeFunction()
{
const int a = 10;
...
}
1:不可以换成const。new操作符是需要执行构造函数的,所以无法在编译期间确定
2:可以换成const。我们也看到,Reference类型的常量(除了String)只能是Null。
3:可以换成const。我们可以在编译期间很明确的说,A等于200。
4:不可以换成const。道理和1是一样的,虽然看起来1,2,3的数组的确就是一个常量。
5:不可以换成readonly,readonly只能用来修饰类的field,不能修饰局部变量,也不能修饰property等其他类成员。
因此,对于那些本质上应该是常量,但是却无法使用const来声明的地方,可以使用static readonly。例如C#规范中给出的例子:
public class Color
{
public static readonly Color Black = new Color(0, 0, 0);
public static readonly Color White = new Color(255, 255, 255);
public static readonly Color Red = new Color(255, 0, 0);
public static readonly Color Green = new Color(0, 255, 0);
public static readonly Color Blue = new Color(0, 0, 255);static readonly需要注意的一个问题是,对于一个static readonly的Reference类型,只是被限定不能进行赋值(写)操作而已。而对其成员的读写仍然是不受限制的。
public static readonly MyClass myins = new MyClass();
…
myins.SomeProperty = 10; //正常
myins = new MyClass(); //出错,该对象是只读的
但是,如果上例中的MyClass不是一个class而是一个struct,那么后面的两个语句就都会出错。
private byte red, green, blue;
public Color(byte r, byte g, byte b)
{
red = r;
green = g;
blue = b;
}
}
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。