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. 连接弹性和命令拦截的 ASP.NET MVC 应用程序中的实体框架

    最近悟出来一个道理,在这儿分享给大家:学历代表你的过去,能力代表你的现在,学习代表你的将来. 十年河东十年河西,莫欺少年穷 学无止境,精益求精    上篇博客我们学习了EF 之 MVC 排序,查询,分 ...

  2. javascript对json对象的序列化与反序列化

    首先引入一个json2.js.官方的地址为:https://github.com/douglascrockford/JSON-js 这里为了方便我直接贴上源代码 /* json2.js 2013-05 ...

  3. url.py中的配置问题

    urlpatterns = [    url(r'^add$', calc_views.add, name='add'),      url(r'^admin/', admin.site.urls), ...

  4. sprint演示

  5. VS2010--2013使用技巧及使用过程中遇到的问题

    Microsoft Visual Studio 2010 --2013默认情况下是不显示代码的行号的,但是在编译出错时,可点击下面输出窗口中的错误提示进行定位.但是这样操作起来你有没有感觉到不方便呢. ...

  6. 关于linux中执行脚本或程序时指定的路径

    假设/mnt/bin 目录下存在一个名为 hello.sh 的可执行文件. 1. 若当前目录是 /mnt/bin ,可以使用 ./hello.sh 来执行这个可执行文件,但是使用 hello.sh 就 ...

  7. html5,新增的元素,fieldset legend

    <form action="">    <fieldset>        <legend>用户注册</legend>       ...

  8. JSON 格式说明

    一维json { "sn" : "CS20160918095444121640", "suitstypes_id" : "47&q ...

  9. ssh 免密码登录

    1.在本机下生成公钥/私钥对. ssh-keygen -t rsa -P '' -P表示密码,-P '' 就表示空密码,也可以不用-P参数,这样就要三车回车,用-P就一次回车.它在/home/yaoy ...

  10. Oracle、Microsoft SQL Server、Mysql

    数据库对比.----1.Oracle:最贵,功能最多,安装最不方便,Oracle环境里的其他相关组件最多,支持平台数量一般,使用中等方便,开发中等方便,运维中等方便,不开源,速度最慢,最安全.---- ...