c#中常量、ReadOnly和Static ReadOnly的差异
不定时更新翻译系列,此系列更新毫无时间规律,文笔菜翻译菜求各位看官老爷们轻喷,如觉得我翻译有问题请挪步原博客地址
在c#中常量中修饰符使字段或局部变量保持不变。ReadOnly应用于c#中的字段,在初始化后值是常量。Static ReadOnly使ReadOnly字段具有类成员的特性。(可通过类名访问)
请仔细阅读关于常量和readonly之间的差异的总结,然后我将试着解释后面的每一点。
常量与Readonly字段在c#中的10个主要区别
| C#中的常量 | C#中Readonly |
|---|---|
| const关键字可以应用于字段或局部变量 | readonly关键字只应用于字段而不是局部变量 |
| 我们必须在公开的时候分配常量字段 | 我们可以在声明或构造函数时指定readonly字段,而不是在任何其他方法中。 |
| 没有分配内存,因为在编译后,在IL代码中嵌入了常量值 | 为Readonly字段分配的动态内存,可以在我们运行时获得值。 |
| 常量在c#中是默认静态的。只能通过类名访问 | Readonly属于需要过类实例访问的对象。要使它成为类成员,我们需要在readonly之前添加static关键字。 |
| 我们可以声明如下所构建的(基本类型)数据类型为常量 Boolean,Char, Byte, SByte, Int16, UInt16, Int32, UInt32, Int64, UInt64, Single, Double, Decimal和string. | 一样不变 |
| 值是常量(因为它属于类) | 根据使用的构造函数(因为它属于类的对象),其值可能会有所不同 |
| 如果我们想要对某些类(非原始类型)声明常量,我们应该将其赋值为null,但是这是没有用的。 | 如果声明一个非基本类型(引用类型),readonly只有引用是不可变的,而不是它包含的对象。(见下面的例子) |
| 不要使用可能导致dll版本问题时发生变化的const字段(参见示例) | 当在运行时获得的值时,没有dll版本控制问题 Static ReadOnly字段的Const字段不能作为ref或out参数传递 |
C#中的常量字段或局部变量:
在C#中我们将使用关键字 "const" 声明常量字段或局部变量.
当你定义一个常量字段时,它的值必须在声明本身的时候被分配,之后我们不能改变它的值。通过下面的例子来了解它
Public class Program
{
const int fieldConstant = 10; //字段
static void Main(string[] args)
{
const int X = 10, Y = 50; //正确的 //局部变量
const int Z = X + Y; //正确的
const int A = X + GettheValue(); // 错误的
}
public static int GettheValue()
{
const int localx=10;
return 10;
}
}
前两行没有任何错误,因为X、Y、Z字段值是在编译时本身进行计算的。但是在第三行中,我们声明了一个变量“A”作为常量,并尝试使用GettheValue()方法在运行时返回值。由于必须在编译时分配常量变量,因此该行不会执行。
c#中的 字段 是在类或结构中直接声明的变量
在上面的示例中 fieldConstant 是一个字段,因为它在程序类中直接声明。
我们可以将局部变量声明为 const ,如上面所示的GetTheValue()方法。
以下构建的值类型可以声明为常量:int, long, char, float, double, decimal, bool, byte, short,string变量也可作为常量
我们可以将非基原类型赋给null来定义一个常量。但是,将一个常量引用类型声明为null是没有用的。
const string constantString = "Hi Iam Constant"; //正确的
const Program program = new Program(); //错误的
const Program program1 = null; //正确的
我们不能将一个常量变量声明为静态变量,因为默认情况下,常量被视为静态成员。
ReadonlyConstant r1=new ReadonlyConstant();// 请参阅下面的类声明代码
Console.WriteLine(r1.ynumber); //错误的
Console.WriteLine(ReadonlyConstant.ynumber);//正确的
作为默认静态的常量变量,我们无法从类的实例中访问它。所以我们不能将const值作为ref或out参数传递。
C#中的ReadOnly字段:
在C#中我们可以将字段声明为ReadOnly而不是局部变量。
ReadOnly字段可以在声明的时候进行初始化,或者只能在对象创建时只调用一次的构造函数中进行初始化,而不是在任何其他方法中。
public class ReadonlyConstant
{
public const int numberOfDays = 7; //字段
public readonly double PI=3.14; //内联初始化
public readonly int znumber;
public readonly List<int> readonlyList;
public ReadonlyConstant()
{
znumber= 50;//构造函数初始化
}
public ReadonlyConstant(int x)
{
znumber=100;
}
public NormalMethod()
{
//readonly int i=0; 这是错误的
}
}
根据使用的构造函数,值可能会有所不同。即,readonly字段属于类的对象。
现在我们将讨论常量和readonly字段之间的区别,正如在第二个点中提到的,常量字段没有分配内存,而值直接嵌入IL代码中。请参阅下面的IL代码图片。

我使用resharper工具查看了上面的示例程序(ReadonlyConstant.cs)的中间语言(IL)代码。
正如您可以看到的IL代码的const字段numberOfdays的值(7)直接嵌入IL代码。其中,readonly字段piValue显示为piValue。该值可在运行时获得。
这就导致了版本控制问题。
C#中常量字段的版本控制:
我将上面的示例程序编译为类库(A),并在另一个项目(B)中使用它作为参考。现在看一下生成的项目B的IL代码

在项目B的代码中,在IL代码中嵌入的常量字段数的值。现在的问题是,在源中(A类库的ReadonlyConstant.cs),常量字段 (numberOfdays )值改为5,并编译并生成一个新的dll
但是,除非我们编译这个项目,否则这个常量字段的新值不会影响B项目。编译后,新的常量字段值将嵌入到项目B的IL代码中。
为了解决这个问题,我们将使用static readonly字段。
C#中的static readonly
由于readonly字段值不同,取决于使用的构造函数。为了使它成为类成员(静态成员)和唯一的类,我们将在变量之前添加static关键字,如下所示。
public class ReadonlyStatic
{
public static readonly string x = "Hi";
public static readonly string y;
public ReadonlyStatic()
{
//y = "Hello"; 这是错误的
}
static ReadonlyStatic()
{
y = "Hello";
}
}
现在我们可以把它作为常量使用,在整个类中,我们将解决dll版本的常量变量问题。可能存在一些性能问题,但不需要构建目标项目,因为值可以在运行时获得。
如上面的示例所示,我们仅在声明或静态构造函数时分配static readonly字段。
C#中Readonly和Static Readonly:
以下是C#中readonly和static readonly字段之间的主要区别。
| C#中的Readonly | C#中的Static Readonly |
|---|---|
| 可以在声明或构造函数的时候分配 | 在声明或静态构造函数时可以分配 |
| 根据使用的构造函数,值可能会不同 | 初始化后值将是常量 |
在C#中何时使用常量和readonly
当值是绝对不变的时候,使用常量,这在时间上是不变的。例如一周的天数是7。这始终是常数。而在使用static readonly时,要避免dll版本问题。
由于在IL内嵌有不变的值,我们可以使用常量修饰符来获得性能上的好处。
如果我们想要对类(或对象)的不同实例使用不同的常量值,请使用readonly。
欢迎转载,转载请注明翻译原文出处(本文章),原文出处(原博客地址),然后谢谢观看
如果觉得我的翻译对您有帮助,请点击推荐支持:)
c#中常量、ReadOnly和Static ReadOnly的差异的更多相关文章
- 读书笔记:const和readonly、static readonly 那些事
C#中表示不变的量(常量)的两种形式:const 和readonly const 是静态常量 readonly 是动态常量 严格的来讲:const 应该称为常量 而readonly 则应称为只读变量. ...
- 【Unity|C#】基础篇(6)——const、readonly、static readonly
[学习资料] <C#图解教程>(第6章):https://www.cnblogs.com/moonache/p/7687551.html 电子书下载:https://pan.baidu.c ...
- static 还是readonly 还是static readonly
一. static 多对象共享一段空间,或者说没有对象概念,就是类的概念,不需要实例化,自动被创建.多用于长期共享.不会为对象的创建或销毁而消失. public class C { ) publi ...
- 如何在 C# 中使用 const,readonly,static
平时在开发时经常会用到 const,readonly,static 关键字,可以肯定这些关键词是完全不同的概念,但有时候他们在用法上很相似以至于在场景中不知道选择哪一个,这篇文章我们就来讨论 C# 中 ...
- 到底是 const 还是 static readonly
真的一样? const 和 static readonly 常在程序中用来声明常量,调用方法也没有什么不同,他们真的一样吗?我们可以做个试验. 程序集内的常量 现在我们建立一个程序,里面有一个MyCl ...
- 【转】const和static readonly
我们都知道,const和static readonly的确很像:通过类名而不是对象名进行访问,在程序中只读等等.在多数情况下可以混用.二者本质的区别在于,const的值是在编译期间确定的,因此只能在声 ...
- (C#) What is the difference between "const" and "static readonly" ?
const int a must be initialized initialization must be at compile time readonly int a can use defaul ...
- const 还是 static readonly
到底是 const 还是 static readonly 真的一样? const 和 static readonly 常在程序中用来声明常量,调用方法也没有什么不同,他们真的一样吗?我们可以做个试 ...
- C# 总结const、 readonly、 static三者区别:
总结const. readonly. static三者区别: (有人问我,看似简单,我也没能立刻回答出来,总结一下,分享一下.) const:静态常量,也称编译时常量(compile-time con ...
随机推荐
- poj 3522 Kruskal
题意:求图的一个生成树使其最大边权与最小边权的差值最小,求其最小值 思路:利用贪心思想,先对边进行排序,然后从最小边开始枚举,每次进行kruskal向右加入边,若加入边刚好能遍历所有点,记录最后加入的 ...
- 【Java IO流】对象的序列化和反序列化
对象的序列化和反序列化 1)对象序列化,就是将Object对象转换成byte序列,反之叫对象的反序列化. 2)序列化流(ObjectOutputStream),是字节的过滤流—— writeObjec ...
- JSON与String之间互转
一,String转json 这个JSON.parse()与eval()都可以实现,但是它们是有区别的, JSON.parse对json字符串要求比eval()更为严格,key名称(例如name)全部必 ...
- 转:JDK中的URLConnection参数详解
针对JDK中的URLConnection连接Servlet的问题,网上有虽然有所涉及,但是只是说明了某一个或几个问题,是以FAQ的方式来解决的,而且比较零散,现在对这个类的使用就本人在项目中的使用经验 ...
- Cobbler批量部署CentOS
简介 Cobbler是一个快速网络安装linux的服务,而且在经过调整也可以支持网络安装windows.该工具使用python开发,小巧轻便(才15k行python代码),使用简单的命令即可完成PXE ...
- 个人作业3——(Alpha阶段)
一.alpha 过程总结 1.这学期的软件工程作业,由于各种事情冲突和时间安排问题,前期并没有太多时间去好好应对,中途有很多次都想放弃.但最后还是咬咬牙在同学的帮助下完成了一些基本任务,在这门课程开始 ...
- 201521123057 《Java程序设计》第5周学习总结
1. 本周学习总结 1.1 尝试使用思维导图总结有关多态与接口的知识点. 2. 书面作业 1.代码阅读:Child压缩包内源代码 1.1 com.parent包中Child.java文件能否编译通过? ...
- JAVA课程设计个人博客 学生成绩管理 201521123001 张陈东芳
1. 团队课程设计博客链接 http://www.cnblogs.com/kawajiang/p/7062407.html 2.个人负责模块或任务说明 我主要负责实现学生信息的添加功能.学生成绩的录入 ...
- 201521123085 《java程序设计》 第9周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常相关内容. 2. 书面作业 本次PTA作业题集异常 常用异常 题目5-1 1.1 截图你的提交结果(出现学号) 1.2 自己以前 ...
- Markdow使用的简单介绍
一个例子: 例子开始 1. 本章学习总结 (字体较大,用法:#你要放大的标题) 今天主要学习了三个知识点 封装 继承 多态 用法: - 封装 - 继承 - 多态 2. 书面作业 Q1. java He ...