MSDN 官方的解释

readonly 关键字是可以在字段上使用的修饰符。当字段声明包括 readonly 修饰符时,该声明引入的字段赋值只能作为声明的一部分出现,或者出现在同一类的构造函数中.
 
很多初学者看完书就会认为,readonly修饰的变量在以后是不能修改的,在以后的开发中从不对ReadOnly的变量进行修改操作,形成思维定势,这个观念是错误的。

首先要明确一点:更改!=重新分配(赋值)

对于简单类型(如int),更改是等于重新赋值,因为默认操作符只有=, 但于对于复杂类型,就不一定了。

例如:

对于class类型,修改其字段属性值。

对于集合类型,增加,移除,清空内容。

我们经常在微软的代码中发现readonly的如下类似的用法:


1     public interface IA { }
2     public class A1 : IA { }
3     public class A2 : IA { }

5     public static class AContainer
6     {
7         private static readonly Dictionary<string, IA> Items = new Dictionary<string, IA>();
8         public static Dictionary<string, IA> As{ get { return Items; } }
9     }

然后在外部可以修改AContainer


 1 class Program
 2     {
 3         static void Main()
 4         {
 5             Console.WriteLine(AContainer.As.Count);
 6             AContainer.As.Add("A1", new A1());
 7             Console.WriteLine(AContainer.As.Count);
 8             AContainer.As.Add("A2", new A2());
 9             Console.WriteLine(AContainer.As.Count);
10             // we can remove all the item of the collection
11             AContainer.As.Clear();
12             Console.WriteLine(AContainer.As.Count);
13             Console.ReadKey();
14         }
15 
16     }

输出:

结论:

可以在外部(非声明和构造函数)对readonly的变量进行修改内容操作。

微软示例和开源代码中用的一种开发扩展的方式就是使用静态的ReadOnly集合容器类,在其中包括默认的实现,然后允许用户在开发中进行添加或替换。

如MVC3中的 ModelBinderProviders,ViewEngines都是类似的实现。

当然我们还可以通过非常规手段(反射,操作内存)来改变readonly的值。

例如反射


 1 using System;
 2 using System.Reflection;
 3 
 4 namespace SOVT
 5 {
 6     public class Foo
 7     {
 8         private readonly int bar;
 9         public Foo(int num) { bar = num; }
10         public int GetBar() { return bar; }
11     }
12 
13     class Program
14     {
15         static void Main()
16         {
17             Foo foo = new Foo(123);
18             Console.WriteLine(foo.GetBar());
19             FieldInfo fieldInfo = typeof(Foo).GetField("bar", BindingFlags.Instance | BindingFlags.NonPublic);
20             if (fieldInfo != null)
21                 fieldInfo.SetValue(foo, 567);
22             Console.WriteLine(foo.GetBar());
23             Console.ReadKey();
24         }
25     }
26 }

输出

ReadOnly关键字修饰的变量可以修改,只是不能重新分配的更多相关文章

  1. [C#基础知识] ReadOnly关键字修饰的变量可以修改,只是不能重新分配

    转自:http://www.cnblogs.com/sujiantao/archive/2011/12/19/2289357.html MSDN 官方的解释 readonly 关键字是可以在字段上使用 ...

  2. 【Java面试题】2 Java中使用final关键字修饰一个变量时,是引用不能变,还是引用的对象不能变?超详细解析

    /* * 问题:使用final关键字修饰一个变量时,是引用不能变,还是引用的对象不能变 * 答: * 使用final关键字修饰一个变量时,是指引用变量不能变,引用变量所指向的对象中的内容还是可以改变的 ...

  3. 使用 final 关键字修饰一个变量时,是引用不能变,还是引用的对象不能变?

    使用 final 关键字修饰一个变量时,是指引用变量不能变,引用变量所指向的对象中的内容还是可以改变的.例如,对于如下语句:final StringBuffer a=new StringBuffer( ...

  4. 使用final关键字修饰一个变量时,是引用不能变,还是引用的对象不能变?

    使用final关键字修饰一个变量时,是指引用变量不能变,引用变量所指向的对象中的内容还是可以改变的.例如,对于如下语句: final StringBuilder a=new StringBuilder ...

  5. 10.使用final关键字修饰一个变量时...

    10.使用final关键字修饰一个变量时,是引用不能变,还是引用的对象不能变? 答:引用不能变,不能将引用再次指向另一个新的对象,但引用所指向的对象中的内容是可以改变的. 补充: 1.对于基本类型,f ...

  6. java中使用final关键字修饰一个变量时,是引用不能变,还是引用的对象不能变?

    java中使用final关键字修饰一个变量时,是引用不能变,还是引用的对象不能变? 是引用对象的地址值不能变,引用变量所指向的对象的内容是可以改变. final变量永远指向这个对象,是一个常量指针,而 ...

  7. 静态static关键字概述和静态static关键字修饰成员变量

    static关键字 概述 关于 static 关键字的使用,它可以用来修饰的成员变量和成员方法,被修饰的成员是属于类的,而不是单单是属 于某个对象的.也就是说,既然属于类,就可以不靠创建对象来调用了 ...

  8. 阶段1 语言基础+高级_1-3-Java语言高级_1-常用API_1_第6节 static静态_12_静态static关键字修饰成员变量

    创建一个学生类 定义成员变量,无参构造,全参构造.成员变量的getter和setter 所在教室必须是一样的,定义所在教室 下面来创建两个学生 只给one的room赋值了.two的教室并没有赋值.都输 ...

  9. final关键字修饰的变量

    final意义:最终的,不可改变的. 1.修饰变量,为常量,值不可变: 2.修饰对象,值可变,引用不变: 3.修饰方法,方法不可重写: 4.修饰类,无子类,不可以被继承,更不可能被重写. 1.fina ...

随机推荐

  1. git cherry-pick. 如何把已经提交的commit, 从一个分支放到另一个分支

    问题 在本地master提交了一个commit(8d85d4bca680a5dbcc3e5cfb3096d18cd510cc9f),如何提交的test_2分之上? 方法 使用cherry-pick 用 ...

  2. 手动启动mongodb和nodejs程序

    最近做单片机去了,以前用的mongodb和nodejs没有配置成服务,居然忘了如何手动启动.在此记录下 一.手动启动mongodb 1.进入cmd 2.在dos下打开mongodb路径E:\mongo ...

  3. 成都app开发:架构一个App需要学会哪些技术呢?

    成都亿合科技小编为您分享: 随着APP应用的流行,越来越多的人想自己学习怎么开发APP应用,那架构一个APP需要学些什么技术呢?首先要了解App都有哪些类型,不同的类型适用于哪些需求,用户可以根据自己 ...

  4. in-list expansion

    in-list expansion也被称作or expansion --针对in后面是常量集合的另外一种处理方法.优化器会把目标sql中in后面的常量集合拆开,把里面的每个常量都提出来形成一个分支,各 ...

  5. Netty之Java堆外内存扫盲贴

    Java的堆外内存本来是高贵而神秘的东西,只在一些缓存方案的收费企业版里出现.但自从用了Netty,就变成了天天打交道的事情,毕竟堆外内存能减少IO时的内存复制,不需要堆内存Buffer拷贝一份到直接 ...

  6. 计划将项目中使用entity framework的要点记录到改栏目下

    ef监控sql执行性能日志.http://www.cnblogs.com/CreateMyself/p/5277681.html http://123.122.205.38/cn_sql_server ...

  7. 学习OpenCV——SVM 手写数字检测

    转自http://blog.csdn.net/firefight/article/details/6452188 是MNIST手写数字图片库:http://code.google.com/p/supp ...

  8. Lua自己实现string.split功能

    local function split(str, d) --str是需要查分的对象 d是分界符 local lst = { } local n = string.len(str)--长度 local ...

  9. generated clock

    内部时钟的定义: create_generated_clock,通过-source,-edges,-divide_by,-multiply_by来执行clock沿. create_generated_ ...

  10. TextToSpeech之阅读文字

    创建阅读类 /** * Created by RongGuang on 2014-11-21. * 中文朗读 */ public class ChineseToSpeech { private Tex ...