在《重构》之Split Temporary Variables中,要使用到final这个类型。
由于例子是用java写的,于是我想找到c#中对应final的修饰符。
结果找到了两个:const和readonly
下面看看这两个有什么区别:
· readonly和const都是用来标识常量的[1]。
· const可用于修饰class的field或者一个局部变量(local variable);而readonly仅仅用于修饰class的field。
· const常量的值必定在编译时就已明确并且恒定的;而readonly常量却有一点不同,那就是其值可以在运行时编译,当然,它也必须遵守作为常量的约束,那就是值必须恒定不变。
· const常量必须在声明的同时对其进行赋值,并且确保该值在编译时可确定并恒定;而readonly常量则可以根据情况选择在声明的同时对其赋予一个编译时确定并恒定的值,或者将其值的初始化工作交给实例构造函数(instant constructor)完成。如:public readonly string m_Now = DateTime.Now.ToString();,m_Now会随着运行时实际情况变化而变化。
· const常量属于类级别(class level)而不是实例对象级别(instant object level),并且它不能跟static结合一起使用,该常量的值将由整个类的所有实例对象共同分享(详细论述参见后面的Remark区域)。
· readonly常量既可以是类级别也可以是实例对象级别的,这取决于它的声明以及初始化工作怎么实施。readonly可以与static结合使用,用于指定该常量属于类级别,并且把初始化工作交由静态构造函数(static constructor)完成(有关如何把readonly常量声明为类级别或实例对象级别的论述清参见后面的Remark区域) 。
· 能被const修饰声明为常量的类型必须是以下的基元类型(primitive type):sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, float, bool, decimal, string。
· object, 数组(Array)和结构(struct)不能被声明为const常量。
· 一般情况下,引用类型是不能被声明为const常量的,不过有一个例外:string。该引用类型const常量的值可以有两种情况,string或null。其实,string虽然是引用类型,但是.NET却对它特别处理,这种处理叫做字符串恒定性(immutable),使得string的值具有只读特性。有关字符串恒定性的内容,可以参考《Microsoft .NET框架程序设计(修订版)》。
从以上关于两者区别的描述可以看出,常量有三种情况:类级别的,实例级别的,局部变量(local variable)。 前两者的区别和实现已经很明显,局部变量(local variable)这个东东我还没见过,下面看一下到底是什么:
看了一下才知道,原来我们在方法中使用的变量就叫做局部变量。比如:
public static void Main()
{
int j=30;
Console.WriteLine(j);//输出结果:30
}
中,里面的j就是局部变量。
因此,可以总结如下:
局部变量:
public static void Main()
{
int j=30;
Console.WriteLine(j);//输出结果:30
}
局部变量标识为常量:
public static void Main()
{
const int j=30;
Console.WriteLine(j);//输出结果:30
}
实例级别的字段:
public class Test
{
public int j=20;
public static void Main()
{
Console.WriteLine(new Test().j);//输出结果:20
}
}
实例级别的字段标识为常量:
public class Test
{
Public const int j=20;
public static void Main()
{
Console.WriteLine(new Test().j);//输出结果:20
}
}
或者:
public class Test
{
Public readonly int j=20;
public static void Main()
{
Console.WriteLine(new Test().j);//输出结果:20
}
}
或者:
public class Test
{
Public readonly int j;
public Test()
{
j=20; //注意,readonly域只能通过初始化器或类的构造函数设置
}
public static void Main()
{
Console.WriteLine(new Test().j);//输出结果:20
}
}
类级别的字段:
public class Test
{
Public static int j=20;
public static void Main()
{
Console.WriteLine(Test.j);//输出结果:20
}
}
类级别的字段标识为常量:
public class Test
{
Public static readonly int j=20;
public static void Main()
{
Console.WriteLine(Test.j);//输出结果:20
}
}