TOC

This article is currently in the process of being translated into Chinese (~84% done).

类 :

Constants (the const keyword)

目前为止,本教程介绍了很多关于变量的内容,顾名思义,变量就是其值总能改变。与此相对应的,C#还引入了一种常量类型,使用const关键字定义。定义常量时,必需当场赋值,之后就再也不能改变这个常量的值了。当某个值永远不会改变,且希望确保其不会被代码(意外地)改变,常量就显得很有用了。

.NET framework中就有很多常量,如,在Math类中就为PI(π )定义了一个常量。

Console.WriteLine(Math.PI);

当然,我们可以定义自己的常量。常量可在方法内定义,象这样:

static void Main(string[] args)
{
    const int TheAnswerToLife = 42;
    Console.WriteLine("The answer to life, the universe and everything: " +  TheAnswerToLife);
}

不过,大多数常量都定义在类一级,让其可供类内部的所有方法,甚至还视其可见性能被类的外部使用(但是,当然不能改变它的值)。一个常量的行为就象一个类的静态成员,不用实例化类就能访问。基于此,请看下面完整的例子,其中定义了两个常量 - 一个私有常量和一个公开常量:

using System;

namespace Constants
{
    class Program
    {
static void Main(string[] args)
{
    Console.WriteLine("The fake answer to life: " + SomeClass.TheFakeAnswerToLife);
    Console.WriteLine("The real answer to life: " +  SomeClass.GetAnswer());
}
    }

    class SomeClass
    {
private const int TheAnswerToLife = 42;
public const int TheFakeAnswerToLife = 43;

public static int GetAnswer()
{
    return TheAnswerToLife;
}
    }
}

注意代码中定义了一个有两个常量的类(SomeClass)。第一个是私有的,因此只能在类的内部访问,另一个是公开的。因此,程序的主代码使用了不同的方法访问这两个常量 - 先进行直接的访问,因为TheFakeAnswerToLife常量是公开,然后再通过GetAnswer()方法的帮助访问另一个。

常量都可以使用那些类型?

由于常量必需现场赋值,之后不能改变,因此给常量的赋值就必需是一个常量表达式,编译器必需在编译时就能够计算出该表达式的值。这表示数字,布尔值及字符串都能用作常量的值,而其它,如,日期时间(DateTime)对象就不能用作常量值。

由于编译器需要立即知道常量的值,也就表示在给常量赋值时有一些操作限制。比如,以下是很好的合法的赋值操作的例子:

const int a = 10;  
const float b = a * 2.5f;

const string s1 = "Hello, world!";  
const string s2 = s1 + " How are you?";

相反的,不能用一个方法调用的返回值或一个非常量类成员来赋值,因这些都不是常量表达式。以下是一些非法赋值的例子:

// NOT possible:
const int a = Math.Cos(4) * 2;
// Possible:
const string s1 = "Hello, world!";
// NOT possible:
const string s2 = s1.Substring(0, 6) + " Universe";

区别在于,当编译器分析代码时需要的是什么,比如,数字,字符串及其它常量,而不是需要运行程序才能得到结果。

常量的替代选择:只读字段

如果想要比类常量限制稍微小点的版本,可以试试readonly关键字。这不能用在方法内部,但可以在类一级定义一个只能在定义时或在类的构造器方法内部赋值的字段。因此,一旦对象正式启用后,readonly字段的值就永远不会变了,也不能被用户改变。请看下面的例子:

class SomeClass
{
    private readonly DateTime rightNow;
    public readonly DateTime later = DateTime.Now.AddHours(2);

    public SomeClass()
    {
this.rightNow = DateTime.Now;
    }
}

代码包含了两个只读字段:第一个是私有的,第二个是公开的(通常只有属性才是公开的,此处为方便说明也就将就了)。第一个字段定义时没有赋值(只读字段定义时可以不赋值,不象常量),另一个则在定义时就赋值了。此外需要注意的一点是,这里使用了DateTime类作为字段的类型,并用一个非常量值给其赋值。换言之,突破了很多常量具有的限制,使只读字段成为常量的一个很好的替代方案。

注意代码在SomeClass类的构造器中给rightNow字段赋值的方式。按照前面的介绍,这里就是给只读字段赋值的最后机会。在此之后,不论是在本类方法里面,还是类的外部,只要给只读字段赋值,就会引发一个编译错误。

总结

常量可以在方法内部定义,也可以定义在类一级。常量定义了在编译时就已知,且定义后不能改变的值。用于常量的典型类型有整数,浮点数,字符串,和布尔值。如果想要多一点点灵活性的话,上文已经介绍过,可以试只读字段。


This article has been fully translated into the following languages: Is your preferred language not on the list? Click here to help us translate this article into your language!