readonly和const

 

   const应该称为常量

   readonly则应称为只读变量

  

   const可用于修饰class的field或者一个局部变量(local variable);

   readonly仅仅用于修饰class的field。

 

  const常量的值必定在编译时就已明确并且恒定的

  readonly常量却有一点不同,那就是其值可以在运行时编译。当然它也必须遵守作为常量的约束,那就是值

  必须恒定不变。

 

  const常量必须在声明的同时对其进行赋值,并且确保该值在编译时可确定并恒定;

  readonly常量则可以根据情况,有两种赋值方式

  a 声明的同时对其赋予一个编译时确定并恒定的值,或者将其值的初始化工作

  b 交给实例构造函数(instant constructor)完成。

  如public readonly string m_Now = DateTime.Now.ToString();,m_Now会随着运行时实际情况变化而化。

 

const常量属于类级别(class level)而不是实例对象级别(instant object level),并且它不能跟static结合一起使用,该常量的值将由整个类的所有实例对象共同分享。

 

readonly常量既可以是类级别也可以是实例对象级别的,这取决于它的声明以及初始化工作怎么实施。readonly可以与static结合使用,用于指定该常量属于类级别,并且把初始化工作交由静态构造函数(static constructor)完成。

 

能被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#region Using directives

using System;

using System.Collections.Generic;

using System.Text;

 

 

namespace ConstantLab

{

    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;

    }

 

    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();

        }

    }

}

 

使用Visual C#在Main()里面使用IntelliSence插入Constant的相关field的时候,发现

①ReadonlyInt和InstantReadonlyInt需要指定Constant的实例对象
(二者都是readonly)

②ConstInt和StaticReadonlyInt却要指定Constant class。  (一个是const,另一个是static readonly)

 

可见

用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两者所修饰的量都说成“常量”,希望没有引起误会。

 

 

原帖地址:http://blog.csdn.net/powerglover/archive/2009/07/15/4350247.aspx

时间: 2024-11-03 08:52:01

readonly和const的相关文章

ASP.NET中readonly与const的区别详解_实用技巧

const是一个修饰常量的关键字,它限定一个变量不允许被改变.使用const在一定程度上可以提高程序的安全性和可靠性,它在程序设计中有着非常重要的作用,给开发人员带来非常方便的应用. 下面我们来建一个控制台应用程序作测试: public class Test { public readonly string name = "George"; public const string coname = "ABC Company LLC"; public Test(str

比较C#中的readonly与const

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

两种常量类型-readonly和const

C#中有两种常量类型,分别为readonly(运行时常量)与const(编译时常量),本文将就这两种类型的不同特性进行比较并说明各自的适用场景. 工作原理 readonly 为运行时常量(动态常量),程序运行时进行赋值,赋值完成后便无法更改,因此也有人称其为只读变量. const 为编译时常量(静态常量),程序编译时将对常量值进行解析,并将所有常量引用替换为相应值.  常量可以为数字.布尔值.字符串或 null 引用,不允许在常数声明中使用 static 修饰符,只能在该字段的声明中初始化. 区

C# FAQ: const和static readonly有什么区别?

ado|区别 我们都知道,const和static readonly的确很像:通过类名而不是对象名进行访问,在程序中只读等等.在多数情况下可以混用.二者本质的区别在于,const的值是在编译期间确定的,因此只能在声明时通过常量表达式指定其值.而static readonly是在运行时计算出其值的,所以还可以通过静态构造函数来赋值.明白了这个本质区别,我们就不难看出下面的语句中static readonly和const能否互换了:1. static readonly MyClass myins =

C# .NET Quiz: const vs. readonly

ado 关于C#中的const和readonly想必使用C# .NET开发的朋友都很了解吧?总结一下const和readonly也就这么几条吧: const和readonly的值一旦初始化则都不再可以改写: const只能在声明时初始化:readonly既可以在声明时初始化也可以在构造器中初始化: const隐含static,不可以再写static const:readonly则不默认static,如需要可以写static readonly: const是编译期静态解析的常量(因此其表达式必须在

[c#基础]关于const和readonly常见的笔试题剖析

引言 有那么几天没更新博客了,发现到了不得不写的地步,总是有那么个声音在强迫自己,虽然工作很累,但是有些东西不写出来,不能原谅自己.今天为什么总结这两个关键字的区别,总觉得这两个关键字的用法用的太习惯了,没想过为什么这么用,就好比为什么一直用右手拿筷子,这么习惯.为什么我要用右手拿筷子,为什么不用左手呢?突然你就这么干了,发现你和周边很不协调,而且还夹不了菜.const和readonly也一样,习惯了,一直这样用,也就没追究过.突然被那么一问,还真说不出来个一二,今天就细细的研究下,到底这东东是

c#中const与readonly区别

原文:c#中const与readonly区别 const 的概念就是一个包含不能修改的值的变量.常数表达式是在编译时可被完全计算的表达式.因此不能从一个变量中提取的值来初始化常量.如果 const int a = b+1;b是一个变量,显然不能再编译时就计算出结果,所以常量是不可以用变量来初始化的. readonly 允许把一个字段设置成常量,但可以执行一些运算,可以确定它的初始值.因为 readonly 是在计算时执行的,当然它可以用某些变量初始化.readonly 是实例成员,所以不同的实例

C#中const 和 readonly 修饰符的用法详解_C#教程

1. 只有C#内置类型(int,double,long等)可以声明为const;结果.类和数组不能声明为const. 2. readonly 是在字段上使用的修饰符,直接以类名.字段访问. 3. const 必须在申明中初始化.之后不能再修改. 4. readonly可以在申明中初始化,也可以在构造函数中初始化,其它情况不能修改. namespace const_and_readonly { class Program { static void Main(string[] args) { Co

[面试题]const与指针

(1)const int *p;   int const *p2; #include <iostream> #include <stdio.h> #include <string.h> using namespace std; int main(){ int a = 3; int b = 4; const int *p; p= &a; int const *p2; p2 = &b; //*p = 5; error: assignment of read-