惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

人人都是产品经理
人人都是产品经理
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
月光博客
月光博客
雷峰网
雷峰网
Google DeepMind News
Google DeepMind News
Y
Y Combinator Blog
Microsoft Security Blog
Microsoft Security Blog
M
MIT News - Artificial intelligence
WordPress大学
WordPress大学
MongoDB | Blog
MongoDB | Blog
V
V2EX
博客园 - 【当耐特】
GbyAI
GbyAI
Stack Overflow Blog
Stack Overflow Blog
I
InfoQ
Martin Fowler
Martin Fowler
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Hugging Face - Blog
Hugging Face - Blog
B
Blog
V
Visual Studio Blog
D
DataBreaches.Net
C
Check Point Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
F
Fortinet All Blogs

博客园 - 寸芒

[原创]作业:家庭消费管理程序,一点代码 [原创]JScript学习摘要1 [随]程序设计模式的有趣解释-追MM [随]SQL Server 和ACCESS 、EXCEL 的数据转换 [原创]treeview简单根据数据库的数据,显示多级节点 [随]测试了下我的Blog价值(汗颜了) [随]C#轻松解决世纪迷题 [随]下了个windows live write 来玩玩 [随] 网站注册随机码的实现 [随]存储过程入门与提高 [原创]涂鸦事件 [随]c#.net常用函数和方法 [原创]到底调用哪个方法 [原创]浅要分析委托和事件 [随]抽象基类与接口,共性与个性的选择 [原创]Box and Unbox [随]c#连接数据库 [随]八荣八耻 [原创]引用类型的转换之感想
[原创]readonly 和const分析
寸芒 · 2007-08-08 · via 博客园 - 寸芒

    咋看下,两者是没什么不同,其实确实有很大的不同点,readonly的好处,可以控制版本的更新,const关键词定义的是常量,是在编译的时候嵌入到程序里,而readonly 定义的是变量,但是这个变量却有于常量相同的用法而已,一旦初始化后,就不能改变!下面,我们利用ILDASM工具分析一下。

程序清单:

using System;

class CunMang

{

    //只定义2个域

    public static readonly int x=5;

    public const int y=4;

}

class main

{

    static void Main(string[]args)

    {

        //输出

        Console.WriteLine(CunMang.x);

        Console.WriteLine(CunMang.y);

    }

}

OK,编译一下,打开ILDASM:

我们先来看一下,CunMang类中,是如何定义的:

哈,看到了没,readonly在编译的时候是没有赋值的,但用const,在编译的时候就已经赋值了,具体怎么赋值的,我们看一下xy各自的构造器:

先看下x的:

分析下:

  IL_0000:  ldc.i4.5  首先在堆栈创建4字节(32位的)的空间,

  IL_0001:  stsfld     int32 CunMang::x  然后把把这个地址引用给x,但是,只有在运行的时候,把这个堆栈最高位(最后赋的值)给x

  IL_0006:  ret     返回

再看一下y的:

分析下:

  IL_0000:  ldarg.0   .0意思就是第一个参数,就是直接运算(也许不恰当)y  就是call

  IL_0001:  call       instance void [mscorlib]System.Object::.ctor()  调用这个构造器直接进行赋值了

  IL_0006:  ret                   返回

综上诉:我们可以看出,readonly 是变量类型的,const是常量类型的,readonly 是在运行的时候初始化,也就是在Main();里,但const就编译时就把值嵌入到程序里了

好,下面,我们看下Main() ,程序执行入口里的代码。清单如下:

分析下:

IL_0000:  ldsfld     int32 CunMang::x 

  IL_0005:  call       void [mscorlib]System.Console::WriteLine(int32)

  IL_000a:  ldc.i4.4

  IL_000b:  call       void [mscorlib]System.Console::WriteLine(int32)

  IL_0010:  ret

―――――――――――――

IL_0000:  ldsfld     int32 CunMang::x  //看到了吧,当你执行这个程序的时候,就是执行Main()的时候,把这个堆栈的值给x,本来的代码是

IL_0000:  ldc.i4.5 IL_0001:  stsfld     int32 CunMang::x  看上面x的构造器,由于构造器(相当于构造函数一样的功能),已经把这个地址引用给x

所以,在Main()里,直接使用x的引用。

―――――――――――――

IL_0005:  call       void [mscorlib]System.Console::WriteLine(int32)  下面,执行了这个显示,并输出

―――――――――――――

由于y的值已经被y的构造器(.ctor)赋值了,所以把这个值压入堆栈,下面就执行这个显示,并输出!