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。

歡迎轉載,轉載請注明翻譯原文出處(本文章),原文出處(原博客地址),然后謝謝觀看

如果覺得我的翻譯對您有幫助,請點擊推薦支持:)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM