2011-06-03 101 views
29

我需要實現這一點:如何在C#中將類實例聲明爲常量?


static class MyStaticClass 
{ 
    public const TimeSpan theTime = new TimeSpan(13, 0, 0); 
    public static bool IsTooLate(DateTime dt) 
    { 
    return dt.TimeOfDay >= theTime; 
    } 
} 

theTime是一個常數(嚴重:-),像π是,在我的情況下,它會是毫無意義的,從設置讀它,例如)。我希望它初始化一次,永不改變。但是C#似乎不允許一個常量被一個函數(構造函數)初始化。如何克服這一點?

回答

48

使用readonly而不是const可以初始化,之後不能修改。那是你在找什麼?

+6

Downvoters:請解釋你爲什麼低估解決OP問題的答案。如果這不是一個好的解決方案,至少要解釋原因。 – ashelvey 2011-06-03 23:13:24

+0

,因爲客觀是非常困難的;) – 2015-05-02 21:58:22

+3

我在我自己的代碼中使用了這個,但是我的肛門保留性格知道每次我做這個事情時都會有一個長期存在的對象來記錄我的應用程序。我有一個長時間運行的應用程序,它已經使用了太多的內存,它只是困擾我。我希望有一個TimeSpan文字會被編譯到我的代碼中。另一種方法是有一個const int,將我的TimeSpan值轉換爲毫秒......但數學。 – Dude0001 2015-07-24 14:52:46

34

常量必須是編譯時間常量,編譯器無法在編譯時計算您的構造函數。使用readonlystatic constructor

static class MyStaticClass 
{ 
    static MyStaticClass() 
    { 
    theTime = new TimeSpan(13, 0, 0); 
    } 

    public static readonly TimeSpan theTime; 
    public static bool IsTooLate(DateTime dt) 
    { 
    return dt.TimeOfDay >= theTime; 
    } 
} 

總的來說,我更喜歡在構造函數,而不是通過直接分配來初始化,你有超過初始化的順序控制。

+0

'theTime'應'靜態'也是如此。所以只有一個,所以上面的例子編譯。 – pickypg 2011-06-03 18:48:37

+4

爲什麼是構造函數?只是將一個成員描述爲公共靜態只讀TimeSpan theTime = new TimeSpan(13,0,0)似乎起作用(至少沒有編譯錯誤)。 – Ivan 2011-06-03 18:49:24

+5

@pickypg - 抱歉我的錯誤 - 修復。 @Ivan - 我對此添加了一條評論。我個人不喜歡直接初始化,因爲你需要搜索一個類來找出初始化的地方。始終在構造函數中放置初始化是一致的,你可以很容易地看到一個類的初始狀態。您還可以直接控制初始化的順序。在一個微不足道的靜態類案例中,可能沒有太大的區別。但好的做法是好的做法 - 特別是在邊緣情況下。 – 2011-06-03 18:53:06

4
public static readonly TimeSpan theTime = new TimeSpan(13, 0, 0); 
7

this link

Constants must be a value type (sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal, or bool), an enumeration, a string literal, or a reference to null.

如果你想創建一個對象,它必須使static readonly完成:

static class MyStaticClass 
{ 
    public static readonly TimeSpan theTime = new TimeSpan(13, 0, 0); 
    public static bool IsTooLate(DateTime dt) 
    { 
    return dt.TimeOfDay >= theTime; 
    } 
} 
9

C#的const不具有含義C++相同的const。在C#中,const用於從本質上定義別名到文本(因此只能用文字初始化)。 readonly更接近你想要的,但請記住它隻影響賦值操作符(除非它的類具有不可變的語義,否則該對象不是真正的常量)。

+3

值得一提的是,靜態只讀字段**可以**通過反射來改變,而'const' **不能**。 – GDS 2016-08-08 23:51:45

0

可以使用只讀關鍵字:

When a field declaration includes a readonly modifier, assignments to the fields introduced by the declaration can only occur as part of the declaration or in a constructor in the same class.

示例(從鏈接的MSDN頁面複製):

class Age 
{ 
    readonly int _year; 
    Age(int year) 
    { 
     _year = year; 
    } 
    void ChangeYear() 
    { 
     //_year = 1967; // Compile error if uncommented. 
    } 
} 
1

恆表示一個靜態成員,其價值永遠無法改變。這意味着在編譯時定義了一個常量值。
的發言:

public const TimeSpan theTime = new TimeSpan(13, 0, 0); 

受到侵犯恆領域的兩條公理:

  • 只有C#內置類型(System.Object的除外)可以被聲明爲const。
  • Iniatialization值必須在編譯時

在問題進行評價,使用的時間跨度類型,這是不內置(預定義的)類型。這意味着csc.exe編譯器無法識別它。
如果您使用內置的C#類型(例如String)並且想要使用編譯時間值初始化常量成員,則仍然會收到錯誤:

public const string MyNumber = SetMyString(); 
private string SetMyString() 
{ 
    return "test"; 
} 

解決這個問題,你可以聲明一個成員:

static readonly 

修改,如果你想在運行時聲明現場只有一次:

public static readonly string MyNumber = SetMyString(); 
private static string SetMyString() 
{ 
return "test"; 
}