readonly vs const [C#]

Features:

  • readonlyconst都是用來標識常量的[1]
  • const可用於修飾class的field或者一個局部變量(local variable);而readonly僅僅用於修飾class的field。
  • const常量的值必定在編譯時就已明確並且恆定的;而readonly常量卻有一點不同,那就是其值可以在運行時編譯,當然,它也必須遵守作爲常量的約束,那就是值必須恆定不變。
  • const常量必須在聲明的同時對其進行賦值,並且確保該值在編譯時可確定並恆定;而readonly常量則可以根據情況選擇在聲明的同時對其賦予一個編譯時確定並恆定的值,或者將其值的初始化工作交給實例構造函數(instant constructor)完成。如:public readonly string m_Now = DateTime.Now.ToString();,m_Now會隨着運行時實際情況變化而變化。
  • const常量屬於類級別(class level)而不是實例對象級別(instant object level),並且它不能跟static結合一起使用,該常量的值將由整個類的所有實例對象共同分享(詳細論述參見後面的Remark區域)。
  • readonly常量既可以是類級別也可以是實例對象級別的,這取決於它的聲明以及初始化工作怎麼實施。readonly可以與static結合使用,用於指定該常量屬於類級別,並且把初始化工作交由靜態構造函數(static constructor)完成(有關如何把readonly常量聲明爲類級別或實例對象級別的論述清參見後面的Remark區域)
  • 能被const修飾聲明爲常量的類型必須是以下的基元類型(primitive type):sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, float, bool, decimal, string
  • object, 數組(Array)和結構(struct)不能被聲明爲const常量。
  • 一般情況下,引用類型是不能被聲明爲const常量的,不過有一個例外:string。該引用類型const常量的值可以有兩種情況,stringnull。其實,string雖然是引用類型,但是.NET卻對它特別處理,這種處理叫做字符串恆定性(immutable),使得string的值具有隻讀特性。有關字符串恆定性的內容,可以參考《Microsoft .NET框架程序設計(修訂版)》

Examples:

Code

using System; namespace ConstantLab { class Program { static void Main(string[] args) { Constant c = new Constant(3); Console.WriteLine("ConstInt = " + Constant.ConstInt.ToString()); Console.WriteLine("ReadonlyInt = " + c.ReadonlyInt.ToString()); Console.WriteLine("InstantReadonlyInt = " + c.InstantReadonlyInt.ToString()); Console.WriteLine("StaticReadonlyInt = " + Constant.StaticReadonlyInt.ToString()); Console.WriteLine("Press any key to continue"); Console.ReadLine(); } } class Constant { public Constant(int instantReadonlyInt) { InstantReadonlyInt = instantReadonlyInt; } public const int ConstInt = 0; public readonly int ReadonlyInt = 1; public readonly int InstantReadonlyInt; public static readonly int StaticReadonlyInt = 4; } }


  • 使用Visual C#在Main()裏面使用IntelliSence插入Constant的相關field的時候,發現ReadonlyInt和InstantReadonlyInt需要指定Constant的實例對象;而ConstInt和StaticReadonlyInt卻要指定Constant class(參見上面代碼)。可見,用const或者static readonly修飾的常量是屬於類級別的;而readonly修飾的,無論是直接通過賦值來初始化或者在實例構造函數裏初始化,都屬於實例對象級別。
  • 一般情況下,如果你需要表達一組相關的編譯時確定常量,你可以考慮使用枚舉類型(enum),而不是把多個const常量直接嵌入到class中作爲field,不過這兩種方式沒有絕對的孰優孰劣之分。

 

Code
using System;

enum CustomerKind
{
    SuperVip,
    Vip,
    Normal
}

class Customer
{
    public Customer(string name, CustomerKind kind)
    {
        m_Name = name;
        m_Kind = kind;
    }

    private string m_Name;
    public string Name
    {
        get { return m_Name; }
    }

    private CustomerKind m_Kind;
    public CustomerKind Kind
    {
        get { return m_Kind; }
    }

    public override string ToString()
    {
        return "Name: " + m_Name + "[" + m_Kind.ToString() + "]";
    }
}
  • 然而,當這種結合使用枚舉和條件判斷的代碼阻礙了你進行更靈活的擴展,並有可能導致日後的維護成本增加,你可以代之以多態,使用Replace Conditional with Polymorphism來對代碼進行重構。(有關多態的詳細介紹,請參見《今天你多態了嗎?》一文。)

Comments:

  • readonly field準確來說應該翻譯成爲“只讀域”,這裏是爲了統一翻譯用語纔將它和const兩者所修飾的量都說成“常量”,希望沒有引起誤會。

 

源出處:http://kb.cnblogs.com/page/42152/1/  http://kb.cnblogs.com/page/42152/2/

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章