轉 C# const readonly static 比較

來源:互聯網
上載者:User

標籤:blog   http   java   使用   strong   資料   io   art   

[csharp] view plaincopy 
  1.  C#中有兩種常量類型,分別為readonly(運行時常量)與const(編譯時間常量),本文將就這兩種類型的不同特性進行比較並說明各自的適用情境。  
  2. 工作原理  
  3.     readonly為運行時常量,程式運行時進行賦值,賦值完成後便無法更改,因此也有人稱其為唯讀變數。  
  4.     const為編譯時間常量,程式編譯時間將對常量值進行解析,並將所有常量引用替換為相應值。  
  5.     下面聲明兩個常量:  
  6.   
  7. public static readonly int A = 2; //A為運行時常量  
  8. public const int B = 3; //B為編譯時間常量  
  9. 下面的運算式:  
  10.   
  11. int C = A + B;  
  12. 經過編譯後與下面的形式等價:  
  13.   
  14. int C = A + 3;  
  15. 可以看到,其中的const常量B被替換成字面量3,而readonly常量A則保持引用方式。  
  16. 聲明及初始化  
  17.     readonly常量只能聲明為類欄位,支援執行個體類型或靜態類型,可以在聲明的同時初始化或者在建構函式中進行初始化,初始化完成後便無法更改。  
  18.     const常量除了可以聲明為類欄位之外,還可以聲明為方法中的局部常量,預設為靜態類型(無需用static修飾,否則將導致編譯錯誤),但必須在聲明的同時完成初始化。  
  19.   
  20. 資料類型支援  
  21.     由於const常量在編譯時間將被替換為字面量,使得其取實值型別受到了一定限制。const常量只能被賦予數字(整數、浮點數)、字串以及枚舉類型。下面的代碼無法通過編譯:  
  22.   
  23. public const DateTime D = DateTime.MinValue;  
  24. 改成readonly就可以正常編譯:  
  25.   
  26. public readonly DateTime D = DateTime.MinValue;  
  27. 可維護性  
  28.     readonly以引用方式進行工作,某個常量更新後,所有引用該常量的地方均能得到更新後的值。  
  29.     const的情況要稍稍複雜些,特別是跨程式集調用:  
  30.   
  31. public class Class1  
  32. {  
  33.     public static readonly int A = 2; //A為運行時常量  
  34.     public const int B = 3; //B為編譯時間常量  
  35. }  
  36.   
  37. public class Class2  
  38. {  
  39.     public static int C = Class1.A + Class1.B; //變數C的值為A、B之和   
  40. }  
  41.   
  42. Console.WriteLine(Class2.C); //輸出"5"  
  43. 假設Class1與Class2位於兩個不同的程式集,現在更改Class1中的常量值:  
  44.   
  45. public class Class1  
  46. {  
  47.     public static readonly int A = 4; //A為運行時常量  
  48.     public const int B = 5; //B為編譯時間常量  
  49. }  
  50.  編譯Class1並部署(注意:這時並沒有重新編譯Class2),再次查看變數C的值:  
  51.   
  52. Console.WriteLine(Class2.C); //輸出"7"  
  53. 結果可能有點出乎意料,讓我們來仔細觀察變數C的賦值運算式:  
  54.   
  55. public static int C = Class1.A + Class1.B;  
  56. 編譯後與下面的形式等價:   
  57.   
  58.    
  59.   
  60. public static int C = Class1.A + 3;  
  61.      因此不管常量B的值如何變,對最終結果都不會產生影響。雖說重新編譯Class2即可解決這個問題,但至少讓我們看到了const可能帶來的維護問題。  
  62.   
  63. 效能比較  
  64.     const直接以字面量形式參與運算,效能要略高於readonly,但對於一般應用而言,這種效能上的差別可以說是微乎其微。  
  65.   
  66. 適用情境  
  67.     在下面兩種情況下:  
  68.     a.取值永久不變(比如圓周率、一天包含的小時數、地球的半徑等)  
  69.     b.對程式效能要求非常苛刻  
  70.     可以使用const常量,除此之外的其他情況都應該優先採用readonly常量。  

 

 

C#中的static 和Java中的static

簡單,兩者用法完全是一致的。從兩方面討論:

1. 變數是屬於類的,不是執行個體層級的。只能通過類名調用,不能通過執行個體調用。

2. 如果在定義時就賦值了,那麼在類初始化的時候,最先完成所有靜態變數的賦值。但是要注意,所有靜態變數的初始化順序是無法確定的。

 

C# 中的const 和Java中的finnal

很長一段時間我一直認為兩者是相同的作用,無非是變數初始化後不能更改,即只能在定義時或者建構函式中賦值。然而這僅僅只是片面的,下面將為大家詳細分析:

1.修飾變數

準確的說C#中的const 等價於 Java中的static final,也就是說,Java中final不具有static的功能。而C#中的const具有static的功能。因此在C#中 public static const string 等將於 public const string。

2.修飾類和方法

此時Java中的final類似C#中的sealed,就是說,final修飾的類不能被繼承,final修飾的方法不能被覆蓋。

而C#中的const不能修飾類和方法。

問題:

1. 私人靜態成員的作用(private static 變數)

字面表示私人的,類外不能使用;靜態,全域變數。看上去很矛盾,又不能被類外使用,要全域的有什麼用。問得好,類中全域也是很有意義的,例如 private static int a = 5,那麼就可以保證變數a在類的初始化過程中將被優先初始化(在建構函式執行之前)。這樣如果對象A的初始化需要對象B的執行個體,那麼就可以用這種申明,以保證在類A在建構函式中能夠使用類B的執行個體。同時private又能夠保證類B的執行個體只能在類A中使用,起到很好的密封作用。

2. 私人最終成員作用(private final 變數)

在類建構函式完成前必須對該成員完成初始化,一旦定義不許更改;該成員只能在本類中使用。執行個體,子類中都不能使用。

private static final修飾的成員在申明的時就被賦值,保證在建構函式中可以被使用,一個被private static final修飾的成員通常表示其他組件的一個執行個體,且變數是類中的全域變數。

private final         修飾的成員在構造中被賦值,表示它是該類全域的私人成員變數,且該類的構造需要傳入他們的初始值,才能完成類的初始化。


 

C# const和static readonly區別

const: 用const修飾符聲明的成員叫常量,是在編譯期初始化並嵌入到用戶端程式 
static readonly: 用static readonly修飾符聲明的成員依然是變數,只不過具有和常量類似的使用方法:通過類進行訪問、初始化後不可以修改。但與常量不同的是這種變數是在運行期初始化。

C# const和static readonly區別樣本:

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Text;  
  4.    
  5. namespace Example02Lib  
  6. {  
  7. public class Class1  
  8. {  
  9. public const String strConst = "Const";  
  10. public static readonly String strStaticReadonly = "StaticReadonly";  
  11. //public const String strConst = "Const Changed";  
  12. //public static readonly String strStaticReadonly = "StaticReadonly Changed";  
  13. }  

用戶端代碼:

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Text;  
  4. using Example02Lib;   
  5. namespace Example02  
  6. {  
  7. class Program  
  8. {  
  9. static void Main(string[] args)  
  10. {  
  11. //修改Example02中Class1的strConst初始值後,只編譯Example02Lib項目  
  12. //然後到資源管理員裡把新編譯的Example02Lib.dll拷貝Example02.exe所在的目錄,執行Example02.exe  
  13. //切不可在IDE裡直接調試運行因為這會重新編譯整個解決方案!!   
  14. //可以看到strConst的輸出沒有改變,而strStaticReadonly的輸出已經改變  
  15. //表明Const變數是在編譯期初始化並嵌入到用戶端程式,而StaticReadonly是在運行時初始化的  
  16. Console.WriteLine("strConst : {0}", Class1.strConst);  
  17. Console.WriteLine("strStaticReadonly : {0}", Class1.strStaticReadonly);   
  18. Console.ReadLine();  
  19. }  
  20. }  

修改後的樣本:

    1. using System;  
    2. using System.Collections.Generic;  
    3. using System.Text;  
    4.    
    5. namespace Example02Lib  
    6. {  
    7. public class Class1  
    8. {  
    9. //public const String strConst = "Const";  
    10. //public static readonly String strStaticReadonly = "StaticReadonly";  
    11. public const String strConst = "Const Changed";  
    12. public static readonly String strStaticReadonly = "StaticReadonly Changed";  
    13. }  
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.