浅析C#中的const与readonly异同

以前只是用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;
    }

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

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;
        }

    }

编译,运行,通过。结果

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的简单分析,也是本人拙见,还望高手们不吝赐教,以求进步。

posted @ 2008-07-26 17:03  Ritchie(乞戈)  阅读(2482)  评论(4编辑  收藏  举报