1. const和readonly的值一旦初始化则都不再可以改写;
  2. const只能在声明时初始化;readonly既可以在声明时初始化也可以在构造器中初始化;
  3. const隐含static,不可以再写static const;readonly则不默认static,如需要可以写static readonly;
  4. const是编译期静态解析的常量(因此其表达式必须在编译时就可以求值);readonly则是运行期动态解析的常量;
  5. const既可用来修饰类中的成员,也可修饰函数体内的局部变量;readonly只可以用于修饰类中的成员

前面是我从网上摘录的,文字太多,懒得自己再总结和打字了.

注意,第四点尤为重要,我用以下代码来说明和验证:

1.建立文本文件,然后改成.cs文件-lib.cs:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. namespace ConstReadonly_Base
  6. {
  7. public class Test
  8. {
  9. public const double PI = 3.14;
  10. public static readonly double pi = 3.14;
  11. }
  12. }

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConstReadonly_Base
{
public class Test
{
public const double PI = 3.14;
public static readonly double pi = 3.14;
}
}

2.在命令行中输入: csc /t:library lib.cs,就会生成一个lib.dll文件.
3.建立文本文件,然后改成.cs文件-demo.cs:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. namespace ConstReadonly_Demo
  6. {
  7. class Program
  8. {
  9. static void Main(string[] args)
  10. {
  11. Console.WriteLine(ConstReadonly_Base.Test.PI);
  12. Console.WriteLine(ConstReadonly_Base.Test.pi);
  13. Console.ReadKey();
  14. }
  15. }
  16. }

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConstReadonly_Demo
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine(ConstReadonly_Base.Test.PI);
Console.WriteLine(ConstReadonly_Base.Test.pi);
Console.ReadKey();
}
}
}

4.在命令行中输入: csc /r:lib.dll demo.cs,也就会生成一个demo.exe文件.
双击,结果如下:
3.14
3.14
5.更改lib.cs为:
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. namespace ConstReadonly_Base
  6. {
  7. public class Test
  8. {
  9. public const double PI = 3.1415;
  10. public static readonly double pi = 3.1415;
  11. }
  12. }

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConstReadonly_Base
{
public class Test
{
public const double PI = 3.1415;
public static readonly double pi = 3.1415;
}
}

6.再次双击demo.exe文件,结果却如下:
3.14
3.1415
(注: 直接双击demo.exe是直接运行,不再编译,上结果也就是运行期结束的结果,相当于跳过了编译)
 
原因是什么呢?请听我慢慢道来.
用ILDasm工具(这里假定你会用),选择lib.dll,内容如下:
双击PI段:
内容为
  1. .field public static literal float64 PI = float64(3.1415000000000002)

.field public static literal float64 PI = float64(3.1415000000000002)

双击pi段:
内容为
  1. .field public static initonly float64 pi

.field public static initonly float64 pi

明显lib.cs被编译成元数据和IL汇编时,PI直接被替换成float64(3.1415000000000002)

而.cctor: void()静态构造函数中,

  1. .method private hidebysig specialname rtspecialname static
  2. void  .cctor() cil managed
  3. {
  4. // Code size       15 (0xf)
  5. .maxstack  8
  6. IL_0000:  ldc.r8     3.1415000000000002
  7. IL_0009:  stsfld     float64 ConstReadonly_Base.Test::pi
  8. IL_000e:  ret
  9. } // end of method Test::.cctor

.method private hidebysig specialname rtspecialname static
void .cctor() cil managed
{
// Code size 15 (0xf)
.maxstack 8
IL_0000: ldc.r8 3.1415000000000002
IL_0009: stsfld float64 ConstReadonly_Base.Test::pi
IL_000e: ret
} // end of method Test::.cctor

pi是动态分配内存的,直到运行时才调用静态构造函数来初始化pi.

如果这时你还是不太明白,让我们接下去看:

用ILDasm工具,选择demo.exe,内容如下:

我们来看看Main函数中我们到底做了些什么:

  1. .method private hidebysig static void  Main(string[] args) cil managed
  2. {
  3. .entrypoint
  4. // Code size       34 (0x22)
  5. .maxstack  8
  6. IL_0000:  nop
  7. IL_0001:  ldc.r8     3.1400000000000001
  8. IL_000a:  call       void [mscorlib]System.Console::WriteLine(float64)
  9. IL_000f:  nop
  10. IL_0010:  ldsfld     float64 ['ConstReadonly-Base']ConstReadonly_Base.Test::pi
  11. IL_0015:  call       void [mscorlib]System.Console::WriteLine(float64)
  12. IL_001a:  nop
  13. IL_001b:  call       valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey()
  14. IL_0020:  pop
  15. IL_0021:  ret
  16. } // end of method Program::Main

.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// Code size 34 (0x22)
.maxstack 8
IL_0000: nop
IL_0001: ldc.r8 3.1400000000000001
IL_000a: call void [mscorlib]System.Console::WriteLine(float64)
IL_000f: nop
IL_0010: ldsfld float64 ['ConstReadonly-Base']ConstReadonly_Base.Test::pi
IL_0015: call void [mscorlib]System.Console::WriteLine(float64)
IL_001a: nop
IL_001b: call valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey()
IL_0020: pop
IL_0021: ret
} // end of method Program::Main

WriteLine()打印PI时,

  1. IL_0001:  ldc.r8     3.1400000000000001
  2. IL_000a:  call       void [mscorlib]System.Console::WriteLine(float64)

IL_0001: ldc.r8 3.1400000000000001
IL_000a: call void [mscorlib]System.Console::WriteLine(float64)

这说明编译时,PI被编译成一个常量.

WriteLine()打印pi时,

  1. IL_0010:  ldsfld     float64 ['ConstReadonly-Base']ConstReadonly_Base.Test::pi

IL_0010: ldsfld float64 ['ConstReadonly-Base']ConstReadonly_Base.Test::pi

这说明编译时,pi被编译成调用ConstReadonly_Base.Test::pi,可见pi量是动态分配和调用的.

总结一下const和readonly的更多相关文章

  1. C#基础知识七之const和readonly关键字

    前言 不知道大家对const和readonly关键字两者的区别了解多少,如果你也不是很清楚的话,那就一起来探讨吧!探讨之前我们先来了解静态常量和动态常量. 静态常量 所谓静态常量就是在编译期间会对变量 ...

  2. const 与 readonly知多少

    原文地址: http://www.cnblogs.com/royenhome/archive/2010/05/22/1741592.html 尽管你写了很多年的C#的代码,但是可能当别人问到你cons ...

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

    引言 有那么几天没更新博客了,发现到了不得不写的地步,总是有那么个声音在强迫自己,虽然工作很累,但是有些东西不写出来,不能原谅自己.今天为什么总结这两个关键字的区别,总觉得这两个关键字的用法用的太习惯 ...

  4. const 和 readonly

    const 和 readonly 的异同 Const readonly 字面意 不变常量,不可修改 只读操作,不可写 初始化 必须在声明的同时赋值 可在声明和构造方法中进行赋值 所属关系 类.即sta ...

  5. C#夯实基础系列之const与readonly

    一.const与readonly的争议       你一定写过const,也一定用过readonly,但说起两者的区别,并说出何时用const,何时用readonly,你是否能清晰有条理地说出个一二三 ...

  6. 读书笔记:const和readonly、static readonly 那些事

    C#中表示不变的量(常量)的两种形式:const 和readonly const 是静态常量 readonly 是动态常量 严格的来讲:const 应该称为常量 而readonly 则应称为只读变量. ...

  7. const和readonly区别

    内容来源<<你必须知道的.NET>>(转载) 标题:什么才是不变:const和readonly 内容: const:用 const 修饰符声明的成员叫常量,是在编译期初始化并嵌 ...

  8. [转]const 与 readonly知多少

    引自:http://www.cnblogs.com/royenhome/archive/2010/05/22/1741592.html 尽管你写了很多年的C#的代码,但是可能当别人问到你const与r ...

  9. const与readonly深度分析(.NET)

    前言 很多.NET的初学者对const和readonly的使用很模糊,本文就const和readonly做一下深度分析,包括: 1. const数据类型的优势 2. const数据类型的劣势 3. r ...

  10. [c#] const 与 readonly

    c# 中 const 与 readonly 关键字看似相同,实则不同.重点在于确定值的时间. const const 很简单,就是一个常量,不可以被 static 修饰,因为被 const 修饰的字段 ...

随机推荐

  1. C#调用C++函数入口点的问题 z

    C++使用 void extern __declspec(dllexport) 函数名()定义的输出函数, 在C#中调用时, 如前文所述, 使用 [DllImport("D:\VS2005P ...

  2. 高并发的常见策略--大型web项目

    一个运营的系统在正式上线后将会遇到各种层级的高并发请求,因此我们必须对此做出相应的策略和技术解决方案,首先我们需要认清系统的高并发由3个层面导致: 1. 传输层 大量用户对系统请求后,将会造成网络带宽 ...

  3. javaweb之javascript结合(三)

    1.案例一:在末尾添加节点 第一步:获取到ul标签 第二步:创建li标签 document.createElement("标签名称")方法 第三步:创建文本 document.cr ...

  4. Asp.Net MVC4新特性指南(2):新特性介绍

       上一章讲解了最基本的MVC4说明.今天就介绍下几种新特性的使用例子:   就当大家有MVC3的基础了.在这个基础上在看下面的介绍就容易多了.1.Web API MVC4包括一个更好的解决方案:A ...

  5. shell常识总结

    #!/bin/bash cmd="ls -lt | grep ^d | awk 'NR==1 {print $9}'" $cmd 这是一个获取文件夹名字的脚本,但是却提示: ls: ...

  6. scala学习笔记(四)样本类与模式匹配

    访问修饰符 格式:private[x]或protected[x],x指某个所属包.类或单例对象,表示被修饰的类(或方法.单例对象),在X域中公开,在x域范围内都可以访问: private[包名]:在该 ...

  7. 整理收藏一份PHP高级工程师的笔试题

    整理了一份PHP高级工程师的笔试题,问题很全面.嗯,基本上这些题都答得不错,那么你应该可以胜任大部分互联网企业的PHP职位了.下面直接上题. 1. 基本知识点 HTTP协议中几个状态码的含义:503, ...

  8. map的基本操作函数及含义

    map的基本操作函数:      C++ Maps是一种关联式容器,包含“关键字/值”对      begin()          返回指向map头部的迭代器      clear()        ...

  9. java 日志技术汇总(log4j , Commons-logging,.....)

    前言 在Tomcat 与weblogic 中的 日志(log4j) 配置系列一 在系列一 中, 有一个问题一直没有解决,就是部署到weblogic 中应用程序如何通过log4j写日志到文件中? 这里仅 ...

  10. C#中如何操作2个list

    博客搬到了fresky.github.io - Dawei XU,请各位看官挪步.最新的一篇是:C#中如何操作2个list.