zoukankan      html  css  js  c++  java
  • c#中常量、ReadOnly和Static ReadOnly的差异

    不定时更新翻译系列,此系列更新毫无时间规律,文笔菜翻译菜求各位看官老爷们轻喷,如觉得我翻译有问题请挪步原博客地址

    本博文翻译自:
    http://www.arungudelli.com/tutorial/c-sharp/10-differences-between-constant-vs-readonly-static-readonly-fields/

    在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代码图片。
    Constant-Readonly-IL-Code

    我使用resharper工具查看了上面的示例程序(ReadonlyConstant.cs)的中间语言(IL)代码。

    正如您可以看到的IL代码的const字段numberOfdays的值(7)直接嵌入IL代码。其中,readonly字段piValue显示为piValue。该值可在运行时获得。

    这就导致了版本控制问题。

    C#中常量字段的版本控制:

    我将上面的示例程序编译为类库(A),并在另一个项目(B)中使用它作为参考。现在看一下生成的项目B的IL代码

    Readonly and Constant field difference at IL Code

    在项目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。

    欢迎转载,转载请注明翻译原文出处(本文章),原文出处(原博客地址),然后谢谢观看

    如果觉得我的翻译对您有帮助,请点击推荐支持:)

  • 相关阅读:
    博客园20071027上海聚会
    上海招聘.NET(C#)程序员
    招人
    漂亮的后台WebUi框架(有源码下载)
    js插件库系列导航
    PrestoSQL(trinodb)源码分析 执行(下)
    Extjs4 (二)
    Struts2(1)简介
    css中的字体
    什么是REST架构
  • 原文地址:https://www.cnblogs.com/chen-jie/p/10-differences-between-constant-vs-readonly-static-readonly-fields.html
Copyright © 2011-2022 走看看