以前只是用const与readonly声明常量,今天在网上看了它们的一些其它属性,觉得有必要弄清楚它们的用法与异同,所以动手找了找,也写了几行代码以呈现,还望大家给予指点。 先贴代码。 定义一个简单类,声明两个公开变量,_const,_readonly. public class ConstReadonly
{ public const string _const; public readonly string _readonly; }
此时会编译会出现错误: 错误 1 常量字段要求提供一个值 (在_const行)。则表明,const变量在声明是就要赋值,而readonly则不一定。 那好,我们就对这两个变量赋值
public class ConstReadonly
{ public const string _const = "const"; public readonly string _readonly; } 然后,在程序中调用此两个变量,
class Program
{ static void Main(string[] args) { ConstReadonly cr = new ConstReadonly(); Console.WriteLine(cr._readonly); Console.WriteLine(cr._const); } }
此时,编译不通过,查看错误 无法使用实例引用访问静态成员“ConstReadonly._const”;改用类型名来限定它。 原来const声明的变量,其为static变量,而readonly则不是。 把cr._const更改为:ConstReadonly._const。
class Program
{ static void Main(string[] args) { ConstReadonly cr = new ConstReadonly(); Console.WriteLine(cr._readonly); Console.WriteLine(ConstReadonly._const);//_const为静态变量 } } 编译通过,输出结果为:
可见,可能不用给_readonly赋初始值。当然,这只是可不可以的讨论,至于实际编程中,要自己把握了。此处,本人查的资料显示为,const编译时赋值,如果没有赋值,则编译不通过;readonly则是在程序运行时赋值,那么它可以同.NET自己值初始null。 下面看一看,给他们赋值变量会出现什么问题。
public class ConstReadonly
{ public string _str = "str"; public const string _const = _str; public readonly string _readonly = _str; } 编译,出现错误: 错误 1 非静态的字段、方法或属性“ConstReadonly._str”要求对象引。 其实,从前面就可以了解到,既然const是静态类型,则只能使用静态字段,方法,属性赋值。此处的ConstReadonly._str则不是静态的。 错误 2 “ConstReadonly._const”的类型为“string”。只能用 null 对引用类型(字符串除外)的常量进行初始化 不说此处,先看下面。 public class ConstReadonly
{ public string _str = "str"; public static string _sstr="sstr"; public const string _const = "const"; public readonly string _readonly = _str; }
编译,又出现错误: 错误 1 字段初始值设定项无法引用非静态字段、方法或属性。 看来readonly也要引用静态的字段,方法或属性。 但是,它没有上面的错误2 在这里,我们可以想一下,const常量是编译时赋值,readonly是运行时赋值。无论是非静态的,或是静态的属性,方法,字段都是在程序运行(或类第一次运行或实例化)的时候赋值,即,它仍然是运行时赋值,不是编译时赋值。既然如此,那么要对const常量赋值,用运行时才能确定的变量或常量,是行不通的。 但是,readonly是运行时赋值,可以用静态方法,属性,字段赋值。至于上面的错误,可以借用下c#语言规范:实例字段的变量初始值设定项不能引用正在创建的实例。因此,在变量初始值设定项中引用 this 是编译时错误,同样,在变量初始值设定项中通过 simple-name 引用任何一个实例成员也是一个编译时错误。上面的_str是一个实例变量,而_sstr则是一个静态变量,据此,可以知道,在readonly初始化时,可以把_sstr赋值给_readonly。 public class ConstReadonly
{ public string _str = "str"; public static string _sstr="sstr"; public const string _const = "const"; public readonly string _readonly=_sstr; } 编译,运行,通过。运行结果。 sstr
public class ConstReadonly
{ public string _str = "str"; public static string _sstr="sstr"; public const string _const = "const"; public readonly string _readonly=_sstr; public ConstReadonly() { _readonly = _str; } } 编译,运行,通过。结果 str 从已上可以看出,const与readonly区别,主要是因为,const为static类型,而readonly不是。所以,我们还可以定义static readonly类型的常量。
public class ConstReadonly
{ public string _str = "str"; public static string _sstr="sstr"; public const string _const; public readonly string _readonly=_sstr; public static readonly string _staticReadonly; public ConstReadonly() { _readonly = _str; } static ConstReadonly() { _staticReadonly = "staticReadonly"; _const="_const"; } } 此时,_staticReadonly = "staticReadonly";是正确的,它可以在静态构造函数中初始化。但是,_const="_const";则不行,原因是在定义_const时,就要进行定义。即使在定义时,_const赋了初始值,也不能在静态构造函数中再次赋值。 此外,除了值类型的常量,const对于引用类型,只能是null或字符串常量。而其它值则不行。但是readonly则不同,它可以是任何类型。并且,对于其代表的常量,不可以改变其引用常量,但是可以改变其引用常量中的,某些可以改变的属性等。
public class ConstReadonly
{ public const string _const="_const"; public readonly Person _readonly; public ConstReadonly() { _readonly = new Person(); } } public class Person { public string name; public Person() { this.name = "Untitled"; } public Person(string name) { this.name = name; } }
上面定义了Person,有一个属性:name。
class Program
{ static void Main(string[] args) { ConstReadonly cr = new ConstReadonly(); Console.WriteLine(cr._readonly.name); cr._readonly.name = "Changed"; Console.WriteLine(cr._readonly.name); } } 编译,运行,通过。输出结果为: Untitled 。 以上是对const与readonly的简单分析,也是本人拙见,还望高手们不吝赐教,以求进步。 |
|