C#中constants域和read-only域的区别
有时你不想在在程序运行时改变域,如运行时程序依靠的数据文件,一个math类的pi值,或者任何在程序运行时你不想改变的值。为了处理这种情况,c#中定义了两个近似的、相关的成员类型:contants和read-only域。
Constants域
从字面可以看出,常数(用关键字const表示)在应用程序运行期间保持不变。当定义某个事物为const时记住两个规则:第一,定义成常数的成员的值是在编译时设置的——或者是由编程者指定,或者是由编译器设置缺省值;第二,一个常数成员的值必须被写为一个字面常数。
为了定义一个常数域,在要定义的成员前使用一个const关键字,如下所示:
using System;
class MagicNumbers
{
public const double pi = 3.1415;
public const int answerToAllLifesQuestions = 42;
}
class ConstApp
{
public static void Main()
{
Console.WriteLine("pi = {0}, everything else = {1}",
MagicNumbers.pi, MagicNumbers.answerToAllLifesQuestions);
}
}
请注意这个代码的一个关键点——不必在客户端实例化MagicNumbers类,因为const成员缺省是静态的。为了更清楚的展示它,我们列出这两个域在MSIL中生成时的情况:
answerToAllLifesQuestions : public static literal int32 = int32(0x0000002A)
pi : public static literal float64 = float64(3.1415000000000002)
Read-only 域
使用const域是非常有用的,因为他清楚的表明了编程者的意图。然而,这只能用于在编译时已经知道值的情况下。所以,当一个域只有在运行时才能知道值而且一旦初始化以后值便不能改变的情况下,编程者该怎么办呢?C#语言的设计者用Read-only域的办法解决了这个问题(在其他语言中一般不会处理)。
当你用readonly关键字定义了一个域时,你只能在一个地方设置这个域的值——构造函数。以后,域的值便不能被自身类或者使用这个类的客户改变。让我们看一个图形应用程序记录屏幕分辨率的例子。你不能用const处理这个问题,因为应用程序直到运行时才能确定终端用户的屏幕分辨率,所以你必须使用这样的代码:
using System;
class GraphicsPackage
{
public readonly int ScreenWidth;
public readonly int ScreenHeight;
public GraphicsPackage()
{
this.ScreenWidth = 1024;
this.ScreenHeight = 768;
}
}
class ReadOnlyApp
{
public static void Main()
{
GraphicsPackage graphics = new GraphicsPackage();
Console.WriteLine("Width = {0}, Height = {1}",
graphics.ScreenWidth,
graphics.ScreenHeight);
}
}
猛一看,这个代码正是我们需要的。然而,还有一点小问题:我们定义的readonly域是一个实例域,这意味着是用户在使用域之前必须先实例化类。这可能也不是什么问题,甚至这正是你想做的——在实例化类的时候正可以初始化readonly域的值。但如果你想要一个被定义成静态的、能在运行时被初始化的常数时该怎么办呢?这时,我们可以定义一个带static和readonly修饰符的域。然后,创建一个构造函数的特殊类型——static constructor。静态函数可以用来初始化static域、readonly域或其他的域。现在我们改变先前的例子,给屏幕分辨率域加上static和readonly,并且增加一个静态构造函数。
using System;
class GraphicsPackage
{
public static readonly int ScreenWidth;
public static readonly int ScreenHeight;
static GraphicsPackage()
{
// Code would be here to
// calculate resolution.
ScreenWidth = 1024;
ScreenHeight = 768;
}
}
class ReadOnlyApp
{
public static void Main()
{
Console.WriteLine("Width = {0}, Height = {1}",
GraphicsPackage.ScreenWidth,
GraphicsPackage.ScreenHeight);
}
}
通过以上说明,我想大家应该明白它们之间的区别了吧。