ReadOnly关键字修饰的变量可以修改,只是不能重新分配
2015-04-05 23:08
253 查看
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 }
输出
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 }
输出
相关文章推荐
- [C#基础知识] ReadOnly关键字修饰的变量可以修改,只是不能重新分配
- [C#基础知识] ReadOnly关键字修饰的变量可以修改,只是不能重新分配
- [C#基础知识] ReadOnly关键字修饰的变量可以修改,只是不能重新分配
- [C#基础知识] ReadOnly关键字修饰的变量可以修改,只是不能重新分配
- JavaSE8基础 final修饰类的成员变量,其只可以被访问,不能被修改
- final关键字可以用来修饰类、方法、变量、参数,不能修饰抽象类和接口
- final关键字可以用来修饰类、方法、变量、参数,不能修饰抽象类和接口
- final关键字可以用来修饰类、方法、变量、参数,不能修饰抽象类和接口
- final关键字可以用来修饰类、方法、变量、参数,不能修饰抽象类和接口
- final关键字可以用来修饰类、方法、变量、参数,不能修饰抽象类和接口
- const修饰的常量 不能被直接修改 但是可以通过指针进行间接修改
- 使用final关键字修饰一个变量时,是引用不能变,还是引用的对象不能变?
- java中使用final关键字修饰一个变量时,是引用不能变,还是引用的对象不能变?
- final关键字修饰变量是引用不能变
- KEIL工具,某变量在watch窗口不能实时修改值,其它变量都可以改
- &符号不能被用于左值, 全局变量的地址是唯一的, 不可以修改的一个左值
- 【Java面试题】2 Java中使用final关键字修饰一个变量时,是引用不能变,还是引用的对象不能变?超详细解析
- 使用final关键字修饰一个变量时,是引用不能变,还是引用的对象不能变?
- final关键字修饰一个变量时,是引用不能变,还是引用的对象不能变
- final关键字修饰一个变量时,是引用不能变,还是引用的对象不能变