C#中的readonly
2015-10-18 15:25
639 查看
const 定义的是静态常在对象初始化的时候赋值.以后不能改变它的值.属于编译时常量。不能用new初始化。
Readonly 是只读变量.属于运行时变量.可以在类constructor里改变它的值.不能作用于局部变量。
const 和 static 不能在一起用,它已经是静态的了。
我们都知道,const和static readonly的确非常像:通过类名而不是对象名进行访问,在程式中只读等等。在多数情况下能混用。
二者本质的差别在于,const的值是在编译期间确定的,因此只能在声明时通过常量表达式指定其值。
而static readonly,在程式中只读, 不过它是在运行时计算出其值的,所以还能通过静态构造函数来对它赋值,
readonly只能用来修饰类的field,不能修饰局部变量,也不能修饰property等其他类成员.
明白了这个本质差别,我们就不难看出下面的语句中static readonly和const能否互换了:
2:能换成const。我们也看到,Reference类型的常量(除了String)只能是Null。
3:能换成const。我们能在编译期间非常明确的说,A等于200。
4:不能换成const。道理和1是相同的,虽然看起来1,2,3的数组的确就是个常量。
5:不能换成readonly,readonly只能用来修饰类的field,不能修饰局部变量,也不能修饰property等其他类成员。
我们看到虽然class1这个字段是readonly的,但是可以使用方法来改变value的值。似乎这个“只读”失去了意义,因为可以修改它的值的话还叫什么“只读”呢?
非也!
从上面的代码中我们可以看到,class1的类型是Class1,是一个引用类型。而引用类型是必须用new关键字为它分配了一块内存以后它才能在后续代码中工作的。也就是说
,class1这个变量仅仅是一块内存地址罢了。
也就是说,这里的“readonly” class1只是无法再重新更改它的引用,但它所引用对象的属性是可以改变的。
那么为什么不用const呢?还是因为class1是引用,是动态分配内存的,不可能在编译阶段就确定它的地址,这点和值类型(包括string)是完全不一样的。
综上所述,可以得出结论: readonly修饰的字段,其初始化仅是固定了其引用(地址不能修改),但它引用的对象的属性是可以更改的。
所以,大胆放心的用readonly吧,这样还可以防止不必要的再赋值,保证了这个对象的安全性。
Readonly 是只读变量.属于运行时变量.可以在类constructor里改变它的值.不能作用于局部变量。
const 和 static 不能在一起用,它已经是静态的了。
我们都知道,const和static readonly的确非常像:通过类名而不是对象名进行访问,在程式中只读等等。在多数情况下能混用。
二者本质的差别在于,const的值是在编译期间确定的,因此只能在声明时通过常量表达式指定其值。
而static readonly,在程式中只读, 不过它是在运行时计算出其值的,所以还能通过静态构造函数来对它赋值,
readonly只能用来修饰类的field,不能修饰局部变量,也不能修饰property等其他类成员.
明白了这个本质差别,我们就不难看出下面的语句中static readonly和const能否互换了:
1. static readonly MyClass myins = new MyClass(); 2. static readonly MyClass myins = null; 3. static readonly B = 10; static readonly A = B* 20; 4. static readonly int[] constIntArray = new int[] { 1, 2, 3 }; 5. void SomeFunction() { const int a = 10; ......... }1:不能换成const。new操作符是需要执行构造函数的,所以无法在编译期间确定
2:能换成const。我们也看到,Reference类型的常量(除了String)只能是Null。
3:能换成const。我们能在编译期间非常明确的说,A等于200。
4:不能换成const。道理和1是相同的,虽然看起来1,2,3的数组的确就是个常量。
5:不能换成readonly,readonly只能用来修饰类的field,不能修饰局部变量,也不能修饰property等其他类成员。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ConsoleApplication1 { //定义一个类 class Class1 { int value; public void ChangeValue1(int _value) { value = _value; } public void ShowValue1() { Console.WriteLine(value); } } //再定义一个类,把第一个类作为变量 class Class2 { readonly Class1 class1;//注意是readonly public Class2() { class1 = new Class1(); } public void ChangeValue2(int _value) { class1.ChangeValue1(_value);// } } class Program { static void Main(string[] args) { } } }
我们看到虽然class1这个字段是readonly的,但是可以使用方法来改变value的值。似乎这个“只读”失去了意义,因为可以修改它的值的话还叫什么“只读”呢?
非也!
从上面的代码中我们可以看到,class1的类型是Class1,是一个引用类型。而引用类型是必须用new关键字为它分配了一块内存以后它才能在后续代码中工作的。也就是说
,class1这个变量仅仅是一块内存地址罢了。
也就是说,这里的“readonly” class1只是无法再重新更改它的引用,但它所引用对象的属性是可以改变的。
那么为什么不用const呢?还是因为class1是引用,是动态分配内存的,不可能在编译阶段就确定它的地址,这点和值类型(包括string)是完全不一样的。
综上所述,可以得出结论: readonly修饰的字段,其初始化仅是固定了其引用(地址不能修改),但它引用的对象的属性是可以更改的。
所以,大胆放心的用readonly吧,这样还可以防止不必要的再赋值,保证了这个对象的安全性。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ConsoleApplication1 { //定义一个类 class Class1 { public readonly int value; public Class1(int _value) { value = _value;//right,只能通过构造函数来对value赋值 } public void ChangeValue1(int _value) { value = _value;//error } } class Program { static void Main(string[] args) { Class1 one = new Class1(2); int b = 2; one.value = b;//error } } }
相关文章推荐
- C#学习日记25---匿名方法 与 Func委托 与 lambda表达式
- C#验证类 可验证:邮箱,电话,手机,数字,英文,日期,身份证,邮编,网址,IP (转)
- C#属性
- C#创建COM组件
- C#学习之操作excel表格
- c# WinForm 中英文智能提示
- c#文件读取和写入的方式总结
- C#动态编译,实现按钮功能动态配置
- C# Winform的自适应分辨率的类
- C#151017学习笔记
- C#使用指针复制字节数组
- C#使用Fixed创建固定大小的缓冲区
- C#不安全代码和stackalloc
- C#不安全代码和Fixed
- C#绘制验证码噪声点
- C#操作指针
- C#使用指针表达式
- C#识别身份证号码(经典版)
- (原创)c#学习笔记03--变量和表达式03--变量04--变量的声明和赋值
- C#启动进程之Process