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

来源:互联网 发布:网络评论引导员 编辑:程序博客网 时间:2024/05/17 21:15

原文地址:http://www.cnblogs.com/sujiantao/archive/2011/12/19/2289357.html


MSDN 官方的解释

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

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

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

例如:

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

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

 

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

public interface IA { }public class A1 : IA { }public class A2 : IA { }public static class AContainer{    private static readonly Dictionary<string, IA> Items = new Dictionary<string, IA>();    public static Dictionary<string, IA> As{ get { return Items; } }}
然后在外部可以修改AContainer

class Program{    static void Main()    {        Console.WriteLine(AContainer.As.Count);        AContainer.As.Add("A1", new A1());        Console.WriteLine(AContainer.As.Count);        AContainer.As.Add("A2", new A2());        Console.WriteLine(AContainer.As.Count);        // we can remove all the item of the collection        AContainer.As.Clear();        Console.WriteLine(AContainer.As.Count);        Console.ReadKey();    }}

输出:

0

1

2

0

结论:

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

 

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

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

 

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

例如反射

using System;using System.Reflection;namespace SOVT{    public class Foo    {        private readonly int bar;        public Foo(int num) { bar = num; }        public int GetBar() { return bar; }    }    class Program    {        static void Main()        {            Foo foo = new Foo(123);            Console.WriteLine(foo.GetBar());            FieldInfo fieldInfo = typeof(Foo).GetField("bar", BindingFlags.Instance | BindingFlags.NonPublic);            if (fieldInfo != null)                fieldInfo.SetValue(foo, 567);            Console.WriteLine(foo.GetBar());            Console.ReadKey();        }    }}
输出

123

567






0 0