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

    ---------------------------------------------

    作者:Ritchie(乞戈)
    出处:http://RitchieChen.cnblogs.com/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。

  • 相关阅读:
    流的创建复制文件
    面试题
    异常
    多态
    继承
    【java】:Junit
    【Java】:ehcache
    【Java】:压缩成多个压缩卷
    【java】:常用工具类
    【javascript】:Highcharts实战
  • 原文地址:https://www.cnblogs.com/RitchieChen/p/1251987.html
Copyright © 2020-2023  润新知