比較C#中的readonly與const )

來源:互聯網
上載者:User
文章目錄
  • Feedback

C#中有兩種常量類型,分別為readonly(運行時常量)與const(編譯時間常量),本文將就這兩種類型的不同特性進行比較並說明各自的適用情境。

工作原理
    readonly為運行時常量,程式運行時進行賦值,賦值完成後便無法更改,因此也有人稱其為唯讀變數。
    const為編譯時間常量,程式編譯時間將對常量值進行解析,並將所有常量引用替換為相應值。
    下面聲明兩個常量:public static readonly int A = 2; //A為運行時常量
public const int B = 3; //B為編譯時間常量

    下面的運算式:

int C = A + B;

    經過編譯後與下面的形式等價:

int C = A + 3;

    可以看到,其中的const常量B被替換成字面量3,而readonly常量A則保持引用方式。

聲明及初始化
    readonly常量只能聲明為類欄位,支援執行個體類型或靜態類型,可以在聲明的同時初始化或者在建構函式中進行初始化,初始化完成後便無法更改。
    const常量除了可以聲明為類欄位之外,還可以聲明為方法中的局部常量,預設為靜態類型(無需用static修飾,否則將導致編譯錯誤),但必須在聲明的同時完成初始化。


資料類型支援

    由於const常量在編譯時間將被替換為字面量,使得其取實值型別受到了一定限制。const常量只能被賦予數字(整數、浮點數)、字串以及枚舉類型。下面的代碼無法通過編譯:public const DateTime D = DateTime.MinValue;

    改成readonly就可以正常編譯:

public readonly DateTime D = DateTime.MinValue;

 


可維護性

    readonly以引用方式進行工作,某個常量更新後,所有引用該常量的地方均能得到更新後的值。
    const的情況要稍稍複雜些,特別是跨程式集調用:public class Class1
{
    public static readonly int A = 2; //A為運行時常量
    public const int B = 3; //B為編譯時間常量
}

public class Class2
{
    public static int C = Class1.A + Class1.B; //變數C的值為A、B之和 
}

Console.WriteLine(Class2.C); //輸出"5"

 

    假設Class1與Class2位於兩個不同的程式集,現在更改Class1中的常量值:

public class Class1
{
    public static readonly int A = 4; //A為運行時常量
    public const int B = 5; //B為編譯時間常量
}

    編譯Class1並部署(注意:這時並沒有重新編譯Class2),再次查看變數C的值:

Console.WriteLine(Class2.C); //輸出"7"

    結果可能有點出乎意料,讓我們來仔細觀察變數C的賦值運算式:

public static int C = Class1.A + Class1.B;

    編譯後與下面的形式等價:

public static int C = Class1.A + 3;

    因此不管常量B的值如何變,對最終結果都不會產生影響。雖說重新編譯Class2即可解決這個問題,但至少讓我們看到了const可能帶來的維護問題。

 

效能比較
    const直接以字面量形式參與運算,效能要略高於readonly,但對於一般應用而言,這種效能上的差別可以說是微乎其微。

適用情境
    在下面兩種情況下:
    a.取值永久不變(比如圓周率、一天包含的小時數、地球的半徑等)
    b.對程式效能要求非常苛刻
    可以使用const常量,除此之外的其他情況都應該優先採用readonly常量。

Tag標籤: c#,.net

Feedback#1樓    回複  引用    

2008-05-26 22:40 by C#愛好者 [未註冊使用者] 正好,學學。謝謝了。#2樓    回複  引用    

2008-05-26 22:40 by 牛 牛 [未註冊使用者] 講的都是些基礎知識了,呵呵學習鞏固了。 #3樓    回複  引用  查看    

2008-05-26 22:50 by StephenJu       怎麼園子裡有的說readonly是定義唯讀變數,也有的說是定義常量?到底是什麼啊?
請問Class1與Class2位於兩個不同的程式集,現在更改Class1中的常量值後,輸出結果怎麼是7?? #4樓    回複  引用  查看    

2008-05-27 01:30 by 水言木       @StephenJu
我覺得叫“唯讀變數”會好點吧,其實大家的意思都是一個。
嚴格來說,常量是必須在聲明時賦值且不能再次賦值的,但readonly卻不是,它可以在建構函式中對其再次賦值,另外常量的值在編譯時間就確定。#5樓    回複  引用    

2008-05-27 08:17 by 風中之羽 [未註冊使用者] const 的概念就是一個包含不能修改的值的變數。
常數運算式是在編譯時間可被完全計算的運算式。因此不能從一個變數中提取的值來初始化常量。
如果 const int a = b+1;b是一個變數,顯然不能再編譯時間就計算出結果,所以常量是不可以用變數來初始化的。

readonly 允許把一個欄位設定成常量,但可以執行一些運算,可以確定它的初始值。
因為 readonly 是在計算時執行的,當然它可以用某些變數初始化。
readonly 是執行個體成員,所以不同的執行個體可以有不同的常量值,這使readonly更靈活。

readonly 關鍵字與 const 關鍵字不同。

1. const 欄位只能在該欄位的聲明中初始化。
readonly 欄位可以在聲明或建構函式中初始化。因此,根據所使用的建構函式,readonly 欄位可能具有不同的值。
2. const 欄位是編譯時間常數,而 readonly 欄位可用於運行時常數。
3. const 預設就是靜態,而 readonly 如果設定成靜態就必須顯示聲明。
4.const 對於參考型別的常數,可能的值只能是 string 和 null。
readonly可以是任何類型

* 需要注意的一個問題是:

對於一個 readonly 的 Reference 類型,只是被限定不能進行賦值(寫)操作而已。而對其成員的讀寫仍然是不受限制的。

public static readonly Class1 my = new Class1();

my.SomeProperty = 10; //正常
my = new Class1(); //出錯,該對象是唯讀

但是,如果上例中的 Class1 不是一個 Class 而是一個 struct,那麼後面的兩個語句就都會出錯。

static readonly:

Java 中 static 是當載入一個類時執行一次的。

C#中是怎麼執行的,我沒有查到。很奇怪幾乎每本java的書都會說static的問題,C#的往往只說怎麼用,但是應該是在main函數調用之前初始化,所以static readonly也是運行時的,可以用變數付值,如:

private static readonly string path = System.Windows.Forms.Application.StartupPath + “aaa”;

--摘自LTP.NET知識庫系列

#6樓    回複  引用  查看    

2008-05-27 08:18 by zmxmiss       學習 學習#7樓    回複  引用  查看    

2008-05-27 08:21 by Da Vinci       Effective C#
規則2: 盡量使用readonly而不是const
只是readonly的效能較差
看情況用了#8樓    回複  引用  查看    

2008-05-27 08:22 by 81       寫的好,不同assembly中對const的處理這個問題,以前的確沒有注意到。#9樓    回複  引用  查看    

2008-05-27 08:26 by Da Vinci       @StephenJu
readonly是動態常量, const是靜態常量
用readonly定義的常量需要分配記憶體
4+3 = 7#10樓    回複  引用  查看    

2008-05-27 08:27 by Da Vinci       @81
所以用const有可能會出錯#11樓    回複  引用  查看    

2008-05-27 08:43 by CoderZh       很好#12樓    回複  引用  查看    

2008-05-27 09:57 by StephenJu       @水言木
@Da Vinci
非常感謝,現在明白了,呵呵!#13樓    回複  引用  查看    

2008-05-27 09:59 by StephenJu       @風中之羽
非常感謝!#14樓    回複  引用  查看    

2008-05-27 11:31 by OOP       恩,寫的非常好。#15樓    回複  引用    

2008-05-27 11:31 by wxc [未註冊使用者] 補充 風中之羽:

const 既可以修飾類中的成員,也可以修飾函數體中的局部變數。
而readonly 只能修飾類中的成員#16樓    回複  引用  查看    

2008-05-27 12:59 by Anytao       寫得很好。
不過我覺得不夠全面,其實static readonly和const更具可比性,在應用範圍上可以更加具體一些,例如readonly不能修飾局部變數,而const可以。。。

另外,“readonly為運行時常量,程式運行時進行賦值,一旦賦值便無法更改”的說法不夠精確,實際上readonly的值是可以更改的,在建構函式內就可以變更。

所以,其實從記憶體角度理解可以看得更加透徹:-)

謝謝你的妙文:-) #17樓    回複  引用  查看    

2008-05-27 13:02 by Anytao       l另外,對於唯讀特性而言,我覺得通過屬性的set和get訪問器來實現可讀可寫對於封裝性而言,有著更加優雅的代碼體驗和可靠性:-)#18樓 [樓主]   回複  引用  查看    

2008-05-27 13:36 by Kenny@Web       @Anytao
謝謝你的建議,已對內容進行補充:-)#19樓    回複  引用  查看    

2008-05-27 15:51 by 求知無傲       晚上看#20樓    回複  引用    

2008-05-27 17:06 by Train-i [未註冊使用者] 說的很詳細啊#21樓    回複  引用  查看    

2008-05-27 19:35 by 曲濱*銘龘鶽       樓主不要誤導小朋友啊;

readonly 絕對不是常量的先說;

這東西叫“唯讀變數”;

只不過看似比較類似常量,的一個偽常量;

C# 代碼

public class SampleClass
{

const int C = 25;
readonly int R = 25;

public void Test()
{

Console.WriteLine(C);
Console.WriteLine(R);
}
}

編譯後

public class SampleClass
{

private const int C = 0x19;
private readonly int R = 0x19;

public void Test()
{
Console.WriteLine(0x19);
Console.WriteLine(this.R);
}
}

簡單的說“常量”是在編譯時間直接放在代碼裡的,並不是指向某個變數。

#22樓    回複  引用    

2008-05-27 20:36 by James Dai [未註冊使用者] static readonly是擷取地址,
const是直接擷取值.類似於淺拷貝與深拷貝#23樓    回複  引用    

2008-08-24 09:51 by lonely_c# [未註冊使用者] 原來學習C#的這麼多啊

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.