C#中有两种常量类型,分别为readonly(运行时常量)与const(编译时常量),本文将就这两种类型的不同特性进行比较并说明各自的适用场景。

工作原理
    readonly为运行时常量,程序运行时进行赋值,赋值完成后便无法更改,因此也有人称其为只读变量。
    const为编译时常量,程序编译时将对常量值进行解析,并将所有常量引用替换为相应值。
    下面声明两个常量:

public static readonly int A = 2; //A为运行时常量
public const int B = 3; //B为编译时常量

下面的表达式:

int C = A + B;

经过编译后与下面的形式等价:

int C = A + 3;

可以看到,其中的const常量B被替换成字面量3,而readonly常量A则保持引用方式。

声明及初始化
    readonly常量只能声明为类字段,支持实例类型或静态类型,可以在声明的同时初始化或者在构造函数中进行初始化,初始化完成后便无法更改。
    const常量除了可以声明为类字段之外,还可以声明为方法中的局部常量,默认为静态类型(无需用static修饰,否则将导致编译错误),但必须在声明的同时完成初始化。

数据类型支持

    由于const常量在编译时将被替换为字面量,使得其取值类型受到了一定限制。const常量只能被赋予数字(整数、浮点数)、字符串以及枚举类型。下面的代码无法通过编译:

public const DateTime D = DateTime.MinValue;

改成readonly就可以正常编译:

public readonly DateTime D = DateTime.MinValue;


可维护性

    readonly以引用方式进行工作,某个常量更新后,所有引用该常量的地方均能得到更新后的值。
    const的情况要稍稍复杂些,特别是跨程序集调用:

public class Class1
{
    public static readonly int A = 2; //A为运行时常量
    public const int B = 3; //B为编译时常量
}

public class Class2
{
    public static int C = Class1.A + Class1.B; //变量C的值为A、B之和 
}

Console.WriteLine(Class2.C); //输出"5"

假设Class1与Class2位于两个不同的程序集,现在更改Class1中的常量值:

public class Class1
{
    public static readonly int A = 4; //A为运行时常量
    public const int B = 5; //B为编译时常量
}

编译Class1并部署(注意:这时并没有重新编译Class2),再次查看变量C的值:

Console.WriteLine(Class2.C); //输出"7"

结果可能有点出乎意料,让我们来仔细观察变量C的赋值表达式:

public static int C = Class1.A + Class1.B;

编译后与下面的形式等价:

public static int C = Class1.A + 3;

因此不管常量B的值如何变,对最终结果都不会产生影响。虽说重新编译Class2即可解决这个问题,但至少让我们看到了const可能带来的维护问题。

性能比较
    const直接以字面量形式参与运算,性能要略高于readonly,但对于一般应用而言,这种性能上的差别可以说是微乎其微。

适用场景
    在下面两种情况下:
    a.取值永久不变(比如圆周率、一天包含的小时数、地球的半径等)
    b.对程序性能要求非常苛刻
    可以使用const常量,除此之外的其他情况都应该优先采用readonly常量。

 
 
分类: C#
标签: .netc#

对C# 中Readonly的再认识

 很多人知道readonly 和 const 以及他们的区别和联系,本文只要对readonly 的一个小特性进行记录,属于读书笔记吧

请看如下代码

    public sealed class AType
{
public static readonly Char[] TestChars = new Char[] {'A', 'B', 'C'};
}

  这句代码很简单 我只是对静态只读字段TestChars赋初始值。这时候如果我问你我现在可以改变TestChars的值吗,你肯定会回答当然不可以,真的是这样吗,请仔细思考下.

请看如下代码

    class Program
{
static void Main(string[] args)
{
AType.TestChars[0] = 'X';
AType.TestChars[1] = 'Y';
AType.TestChars[2] = 'Z';
Console.WriteLine(AType.TestChars[0]);
Console.Read();
}
}

  这个输出结果是什么呢,是编译的时候报错还是会输出修改后的值“X”呢 答案是输出为“X”

  在看如下代码

    class Program
{
static void Main(string[] args)
{
AType.TestChars = new Char[] {'X', 'Y', 'Z'};
Console.WriteLine(AType.TestChars[0]);
Console.Read();
}
}

  这个输出结果又是什么呢。。。 答案是编译出错提示“无法对静态只读字段赋值”

  看到这里,我想大家都明白了:当某个字段是引用类型,并且该字段标记为readonly时,那么不可改变的是引用,而非字段引用的对象.

对C# 中Readonly的再认识的更多相关文章

  1. 关于C#中readonly

    关于C#中readonly的一点小研究 关于C#中readonly的一点小研究   可能园子里有不少文章已经说明了这个问题了,但是我在这里写这篇博客只是写写自己的一些体会,也权当是整理归纳,高手莫见笑 ...

  2. winform中button点击后再点击其他控件致使button失去焦点,此时button出现黑色边线,去掉黑色边线的方法

    winform中button点击后再点击其他控件致使button失去焦点,此时button出现黑色边线,去掉黑色边线的方法 button的FlatAppearence属性下,设置BorderSize= ...

  3. 关于C#中readonly的一点小研究

    可能园子里有不少文章已经说明了这个问题了,但是我在这里写这篇博客只是写写自己的一些体会,也权当是整理归纳,高手莫见笑. ===============正文分割线================== 现 ...

  4. Spring 事务中 readOnly 的解释

      spring 中事务的PROPAGATION_REQUIRED,Readonly的解释  (2012-11-21 16:29:38) 转载▼ 标签:  杂谈                  一. ...

  5. 小鱼提问2 属性访问器中get,set再用public修饰行吗,private呢?

    /// <summary> /// 是否有一个用户正在连接服务器中 /// </summary> public bool IsConnectting { get { retur ...

  6. python+opencv选出视频中一帧再利用鼠标回调实现图像上画矩形框

    最近因为要实现模板匹配,需要在视频中选中一个目标,然后框出(即作为模板),对其利用模板匹配的方法进行检测.于是需要首先选出视频中的一帧,但是在利用摄像头读视频的过程中我唯一能想到的方法就是: 1.在视 ...

  7. Q他中的乱码再理解

    Qt版本有用4的版本的也有用5的版本,并且还有windows与linux跨平台的需求. 经常出现个问题是windows的解决了,源代码放到linux上编译不通过或者中文会乱码,本文主要是得出一个解决方 ...

  8. IOS中录音后再播放声音太小问题解决

    1.AVAudioSessionCategory说明 1.1 AVAudioSessionCategoryAmbient 或 kAudioSessionCategory_AmbientSound 用于 ...

  9. PL/SQL中复制中文再粘贴出现乱码问题的解决【转】

    前不久!我对我的windowsxp做了一番大规模的设置:包括区域.系统.网络等方面的,结果当我设置完成以后,发现如果我从一些软件上复制内容到记事本里面会出现乱码,而且如果复制到word里面也不能够正常 ...

随机推荐

  1. 怎样下载并编译Android4.0内核源代码goldfish(图文)

    关于怎样下载Android4.0源代码,请查看我的博客内还有一篇文章(相同是图文教程): http://blog.csdn.net/flydream0/article/details/7036156 ...

  2. jmeter之自定义java请求性能测试

    一.环境准备         1.新建一个java工程         2.导入jar包:ApacheJMeter_core.jar     ApacheJMeter_java.jar         ...

  3. DevExpress gridview下拉框的再次研究

    原文:DevExpress gridview下拉框的再次研究 前几天写了一篇关于研究DevExpress gridview下拉框的随笔(DevExpress gridview下拉框repository ...

  4. 【麦子学院】OpenCV教程函数总结

    个自带样例. parter 1: No1. adaptiveskindetector.cpp 利用HSV空间的色调信息的皮肤检測,背景不能有太多与肤色相似的颜色.效果不是特别好. No2. bagof ...

  5. 大约Android 3.0后AsyncTask默认的单线程分析

    在Android下了很大的后台操作在需要的情况下.通常用于AsyncTask这个类.比方说,网络负载形象.访问server接口.一般的情况是使用一个的一例AsyncTask对象mTask,复制Asyn ...

  6. leetcode[50] N-Queens

    题目:给定一个n,那么在n*n的棋盘里面放国际象棋的皇后,皇后之间互不在攻击范围.(皇后的攻击范围是她所在位置的哪一行,那一列,和她的正负1的对角线) The n-queens puzzle is t ...

  7. Python开发环境Wing IDE 5.0测试第八版发布

    Wing IDE是著名的Python开发工具,是Wingware公司的主要产品.从1999年起,Wingware公司便开始专注于Python开发设计.Wing IDE在十几年的发展中,不管完善.其强大 ...

  8. Repository 仓储

    Repository 仓储 写在前面 首先,本篇博文主要包含两个主题: 领域服务中使用仓储 SELECT 某某某(有点晕?请看下面.) 上一篇:Repository 仓储,你的归宿究竟在哪?(二)-这 ...

  9. jenkins+svn+gradle自动化部署笔记

    自己虚拟机jekins配置:(jenkins+svn+gradle)自动化部署,1.linux配置好jdk,解压tomcat,将 jenkins.war翻到webapps目录下.2.系统管理-管理用户 ...

  10. {{angular.js 使用技巧}} - 实现计算列属性

    前端MV*框架现在有很多,其中某些框架有计算列(又叫监控属性),比如:微软推荐的 Knockout.js 和博客园司徒正美的 avalon.js 框架. 本人只使用过 Knockout.js,aval ...