zoukankan      html  css  js  c++  java
  • [C#基础知识] ReadOnly关键字修饰的变量可以修改,只是不能重新分配

    转自:http://www.cnblogs.com/sujiantao/archive/2011/12/19/2289357.html

    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 }
    复制代码

    输出

  • 相关阅读:
    Linux(centos)下安装JDK
    springmvc的面试知识点总结
    建造者模式
    PHP原型模式
    PHP适配器模式
    php备忘录模式
    PHP代理模式proxy
    单例模式
    工厂模式
    结构模式
  • 原文地址:https://www.cnblogs.com/mengfff/p/5121600.html
Copyright © 2011-2022 走看看