转载:readonly和const比较

原文地址:http://www.cnblogs.com/panjun-Donet/archive/2008/03/28/1127680.html

前天犯了个低级错误,是关于readonly的,总结了一下:    
C#的readonly关键字只能在字段上面使用
public readonly TcpClient client;
不能在类,方法,属性上面使用readonly!!
顺便看了一下readonly和const的区别:

  • readonly和const都是用来标识常量的。
  • 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框架程序设计(修订版)》

Examples:

using System;

public class Order
{
    public Order()
    {
        Guid guid = Guid.NewGuid();
        ID = guid.ToString("D");
    }

    // 对于每一份订单,其订单序号都是实时确定的常量。
    public readonly string ID;

    public override string ToString()
    {
        return "Order ID: " + ID;
    }
}

Explaintion:

  • 如果结合数据库使用,ID field通常都会都会与某个表的主健(primary key)关联起来,如Orders表的OrderID。
  • 数据库的主健通常采用以下三种方式:
    • 自动递增值。你可以通过把DataColumn.AutoIncrement设定为true值来激活自动递增特性。
    • 唯一名称。这个是使用自己定义的算法来生成一个唯一序列号。
    • GUID(全局唯一标识符)。你可以通过System.Guid结构来生成GUID,如上例。

using System;

class Customer
{
    public Customer(string name, int kind)
    {
        m_Name = name;
        m_Kind = kind;
    }

    public const int NORMAL = 0;
    public const int VIP = 1;
    public const int SUPER_VIP = 2;

    private string m_Name;
    public string Name
    {
        get { return m_Name; }
    }

    private readonly int m_Kind;
    public int Kind
    {
        get { return m_Kind; }
    }

    public override string ToString()
    {
        if(m_Kind == SUPER_VIP)
            return "Name: " + m_Name + "[SuperVip]";
        else if(m_Kind == VIP)
            return "Name: " + m_Name + "[Vip]";
        else
            return "Name: " + m_Name + "[Normal]";
    }
}

Remarks:

  • 一般情况下,如果你需要声明的常量是普遍公认的并作为单个使用,例如圆周率,黄金分割比例等。你可以考虑使用const常量,如:public const double PI = 3.1415926;。如果你需要声明常量,不过这个常量会随着实际的运行情况而决定,那么,readonly常量将会是一个不错的选择,例如上面第一个例子的订单号Order.ID。
  • 另外,如果要表示对象内部的默认值的话,而这类值通常是常量性质的,那么也可以考虑const。更多时候我们对源代码进行重构时(使用Replace Magic Number with Symbolic Constant),要去除魔数(Magic Number)的影响都会借助于const的这种特性。
  • 对于readonly和const所修饰的变量究竟是属于类级别的还是实例对象级别的问题,我们先看看如下代码:

Using directives

namespace ConstantLab
{
    class Program
    {
        static void Main(string[] args)
        {
            Constant c = new Constant(3);
            Console.WriteLine("ConstInt = " + Constant.ConstInt.ToString());
            Console.WriteLine("ReadonlyInt = " + c.ReadonlyInt.ToString());
            Console.WriteLine("InstantReadonlyInt = " + c.InstantReadonlyInt.ToString());
            Console.WriteLine("StaticReadonlyInt = " + Constant.StaticReadonlyInt.ToString());

            Console.WriteLine("Press any key to continue");
            Console.ReadLine();
        }
    }

    class Constant
    {
        public Constant(int instantReadonlyInt)
        {
            InstantReadonlyInt = instantReadonlyInt;
        }

        public const int ConstInt = 0;

        public readonly int ReadonlyInt = 1;

        public readonly int InstantReadonlyInt;

        public static readonly int StaticReadonlyInt = 4;
    }
}

  • 使用Visual C#在Main()里面使用IntelliSence插入Constant的相关field的时候,发现ReadonlyInt和InstantReadonlyInt需要指定Constant的实例对象;而ConstInt和StaticReadonlyInt却要指定Constant class(参见上面代码)。可见,用const或者static readonly修饰的常量是属于类级别的;而readonly修饰的,无论是直接通过赋值来初始化或者在实例构造函数里初始化,都属于实例对象级别。
  • 一般情况下,如果你需要表达一组相关的编译时确定常量,你可以考虑使用枚举类型(enum),而不是把多个const常量直接嵌入到class中作为field,不过这两种方式没有绝对的孰优孰劣之分。

using System;

enum CustomerKind
{
    SuperVip,
    Vip,
    Normal
}

class Customer
{
    public Customer(string name, CustomerKind kind)
    {
        m_Name = name;
        m_Kind = kind;
    }

    private string m_Name;
    public string Name
    {
        get { return m_Name; }
    }

    private CustomerKind m_Kind;
    public CustomerKind Kind
    {
        get { return m_Kind; }
    }

    public override string ToString()
    {
        return "Name: " + m_Name + "[" + m_Kind.ToString() + "]";
    }
}

  • 然而,当这种结合使用枚举和条件判断的代码阻碍了你进行更灵活的扩展,并有可能导致日后的维护成本增加,你可以代之以多态,使用Replace Conditional with Polymorphism来对代码进行重构。(有关多态的详细介绍,请参见《今天你多态了吗?》一文。)

Comments:

  • readonly field准确来说应该翻译成为“只读域”,这里是为了统一翻译用语才将它和const两者所修饰的量都说成“常量”,希望没有引起误会。
时间: 2024-10-13 09:27:27

转载:readonly和const比较的相关文章

[C#]readonly vs const

C#中的readonly和const两个关键字都可以用来定义系统变量,那两者之间有什么区别呢? 1. const变量赋值后,就不可以对其进行修改.且在定义时就需要给它赋值,使用const修饰的变量是static的.可以使用YourClass.ConstantName的方式进行访问: 2. readonly变量可以在定义时赋值,也可以在构造方法中赋值或者修改定义时赋给的初始值: 另外还有一个细微的差别.看下面的场景,我在AssemblyA中定义了一个类如下: public class Readon

我所理解的readonly和const

最近要给学校软件小组新成员讲几次课,所以把很多以前懒得学习的和模糊不清的知识点,重新学习了一下. MSDN是这样解释的: readonly 关键字与 const 关键字不同. const 字段只能在该字段的声明中初始化. readonly 字段可以在声明或构造函数中初始化. 因此,根据所使用的构造函数,readonly 字段可能具有不同的值. 另外,const 字段为编译时常数,而 readonly 字段可用于运行时常数. 什么是编译时常数,什么是运行时常数呢.我想做下面的实验,关于readon

readonly和const的区别

readonly与const的区别1.const常量在声明的同时必须赋值,readonly在声明时可以不赋值2.readonly只能在声明时或在构造方法中赋值(readonly的成员变量可以根据调用不同的构造方法赋不同的值)3.const前面不能添加static(因为Const本来就是一个静态常量),readonly前面可以添加static4.const在编译的时候赋值,readonly在运行的时候赋值5.const能在方法内声明,readonly不能在方法内声明 class ReadOnlyA

readonly 与 const

readonly MSDN定义:readonly 关键字是可以在字段上使用的修饰符.当字段声明包括 readonly 修饰符时,该声明引入的字段赋值只能作为声明的一部分出现,或者出现在同一类的构造函数中. readonly修饰的字段只能在两个地方对其赋值,第一个是初始化字段的时候,第二个是构造函数中. 1 class Age 2 { 3 //第一个可赋值的地方 4 //private readonly int _year = 20; 5 readonly int _year; 6 7 Age(i

[转载]关于C++ const 的全面总结

C++中的const关键字的用法非常灵活,而使用const将大大改善程序的健壮性,本人根据各方面查到的资料进行总结如下,期望对朋友们有所帮助. Const 是C++中常用的类型修饰符,常类型是指使用类型修饰符const说明的类型,常类型的变量或对象的值是不能被更新的. 一.Const作用    如下表所示: No. 作用 说明 参考代码 1 可以定义const常量 const int Max = 100; 2 便于进行类型检查 const常量有数据类型,而宏常量没有数据类型.编译器可以对前者进行

Break 、Continue 和ReadOnly、Const和Ref和Out params

Break和Continue区别 之前对于Break和Continue:ReadOnly和Const:ref和out,params之类的基础东东学习过,但是一直没有仔细去研究到底是怎么一回事儿,最近在开发中用到了,仔细来做个总结: 1.Break和Continue //break是跳出整个循环体,不再执行本循环,continue是结束单次循环,继续下一次循环. //更多问题 联系QQ 931697811(夜雨梧桐) 1 #region Break测试 2 3 Console.WriteLine(

C#中的readonly与const

比较C#中的readonly与const C#中有两种常量类型,分别为readonly(运行时常量)[read-run]与const(编译时常量)[const-compile],本文将就这两种类型的不同特性进行比较并说明各自的适用场景. 工作原理     readonly为运行时常量,程序运行时进行赋值,赋值完成后便无法更改,因此也有人称其为只读变量.    const为编译时常量,程序编译时将对常量值进行解析,并将所有常量引用替换为相应值.    下面声明两个常量:  public stati

C#中的readonly跟const用法小结

总结一下常量和只读字段的区别: 由来: 笔者也是在看欧立奇版的<.Net 程序员面试宝典>的时候,才发现自己长久以来竟然在弄不清出两者的情况下,混用了这么长的时间.的确,const与readonly 很像,都是将变量声明为只读,且在变量初始化后就不可改写.那么,const与readonly 这两个修饰符到底区别在什么地方呢?其实,这个牵扯出C#语言中两种不同的常量类型:静态常量(compile-time constants)和动态常量(runtime constants).这两者具有不同的特性

C#基本知识点-Readonly和Const的区别

目录 什么是静态常量(Const)和动态常量(Readonly) 静态常量(Const)和动态常量(Readonly)之间的区别 动态常量(Readonly)被赋值后不可以改变 总结 什么是静态常量(Const)和动态常量(Readonly) 先解释下什么是静态常量(Const)以及什么是动态常量(Readonly). 静态常量(Const)是指编译器在编译时候会对常量进行解析,并将常量的值替换成初始化的那个值. 动态常量(Readonly)的值则是在运行的那一刻才获得的,编译器编译期间将其标示