相关文章推荐
知识渊博的冰棍  ·  visual studio ...·  2 月前    · 
豪爽的海龟  ·  JavaScript定时器setInterv ...·  1 年前    · 

以前只是用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为静态变量

编译通过,输出结果为:

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;

编译,运行,通过。运行结果。

const
对于readonly变量,还可以在构造函数中初始化。

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;

编译,运行,通过。结果

const

从已上可以看出,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
Changed

以上是对const与readonly的简单分析,也是本人拙见,还望高手们不吝赐教,以求进步。