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

MSDN 官方的解释

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

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

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

例如:

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

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

 

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

1      public  interface IA { }
2      public  class A1 : IA { }
3      public  class A2 : IA { }
4 
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 }

 

输出

 

 

转载于:https://www.cnblogs.com/sujiantao/archive/2011/12/19/2289357.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值