2010-02-08 23 views
39

一位同事剛剛在C#中創建了以下構造(示例代碼已簡化)。他的目標是縮短其餘代碼中所有預定義字符串的符號。C#靜態類與預定義字符串的struct

public struct PredefinedStrings 
{ 
    public const string VeryLongName = "Very Long Name"; 
    public const string AnotherVeryLongName = "Another Very Long Name"; 
    public const string TheLastVeryLongName = "The Last Very Long Name"; 
} 

public static void MethodThatUsesTheNames() 
{ 
    Console.WriteLine(PredefinedStrings.VeryLongName); 
    Console.WriteLine(PredefinedStrings.AnotherVeryLongName); 
    Console.WriteLine(PredefinedStrings.TheLastVeryLongName); 
} 

雖然看上去做工精細他,我不能停止想知道他是否應該使用一個靜態類,而不是一個結構或是否有實現這一目標更優雅的方式。

這樣做的首選方法是什麼?也請解釋原因。

+5

榮譽給您的同事!我的同事很少使用const,而且我們的字符串分散在我們的代碼中!大聲笑 我認爲,雖然,靜態類是有點標準。 – 2010-02-08 16:49:23

+0

我正在考慮這樣做,但感覺我是過度設計的東西。我通常有2/3的罷工和重構方法,因爲我最初分散了字符串文字,然後一旦我在另一個方法或類中再次需要相同的字符串,我將它提取到靜態類中。但它可能有點乏味。 – ozzy432836 2017-11-16 00:18:04

回答

34

隨着struct解決方案,有什麼能阻止一些其他的代碼做new PredefinedStrings(),不會做什麼壞事,但東西是語義混淆允許。使用靜態類時,編譯器將禁止爲您創建。毫無疑問,靜態類是在框架中提供常量的首選方式。

編輯補充,我說,沒有證據第二部分 - 因爲我已經搜查,合理很快找到System.Net.Mime.DispositionTypeNamesSystem.Net.WebRequestMethods.Http

+0

這可能是使用struct首先讓我皺眉頭的原因,但我沒有沒有考慮檢查'公約'。感謝您的高舉。 這個答案對於在結構和靜態類之間作出選擇非常有用,並且可能足以完成這項工作。不過,我將不得不檢查在這裏使用資源文件是否合適。 – 2010-02-08 18:55:01

+0

我接受這個答案,因爲它似乎適合這種特殊情況,因爲字符串改變的可能性極小。使用資源文件很有趣,但是目前的代碼增加了太多的複雜性。 – 2010-02-09 09:05:44

0

在我的這個練習中,我們使用了Dictionary<enumNameType, string>。 enumNameType是你可以擁有的不同類型的名字(在你的情況下)......這個字典被包裝在一個靜態類中並被緩存 - 我們只是在第一次使用它時創建它,然後返回相同的對象...

我希望這對你也有用!

+0

這比使用常量值有什麼好處?有了字典,你可以快速查找,是的,但不像直接引用常量值那麼快。 – 2010-02-08 16:51:18

+0

@Dan好處是我們重用了enum類型的命名。我們可以在任何地方使用它的語義需求,並且這種代表術語的枚舉類型與字典中的用戶友好命名法相關聯。 – anthares 2010-02-08 16:55:09

+0

聽起來就像你正在談論的有一種有效的方法來從一個枚舉*得到一個字符串,你實際上將它用作一個枚舉*。我得到的印象是,OP更關心的是你只關心一個常量字符串值的情況;但我可能是錯的。 – 2010-02-08 17:13:48

5

此代碼沒有任何功能錯誤。但在風格上,我同意靜態類更好。靜態類聲明類型的意圖是僅保存靜態/常量數據。

27

我更喜歡字符串都在資源文件中,而不是嵌入代碼中 - 主要是爲了國際化的原因。然後可以通過一個靜態類來訪問它,並將值作爲屬性成員。

+2

+1,這是答案。不僅僅是爲了國際化,而且使用資源文件可以讓你糾正錯誤或更新你的字符串,而無需重新構建整個應用程序。 – 2010-02-08 16:48:02

+3

有趣的我比這個答案早說同樣的事情..我的upvotes在哪裏? :P – 2010-02-08 17:07:53

+3

在這種情況下,我們非常確定字符串不會改變,對於這種特殊情況,使用資源文件似乎有點矯枉過正。一個靜態類將完成這項工作(現在)。不過,我會記住這一點,以備將來使用。謝謝! – 2010-02-09 09:02:16

22

除了static classstruct,爲什麼不考慮將resource文件用於常量字符串呢?這些可以很容易地訪問爲SomeNamespace.ResourceName.KeyName,並根據他們在你的項目中的位置可以外部管理,無需重新編譯,如果需要的話...

+1

檢查時間戳,你1分鐘後,但我會給你+1 :) – Andrew 2010-02-08 18:10:33

+1

LOL謝謝。我早先提高你的... – 2010-02-08 20:49:57

1

我認爲靜態更好,這是我的推理。如果此代碼存在於某個庫中,而另一段代碼使用此庫,如果常量字段的值發生更改,則不僅需要重新編譯該庫(duh),而且還必須重新編譯消耗此代碼的代碼圖書館也是如此。其原因是,編譯會在引用它們的地方插入常量值。如果您使用靜態,則不會出現此問題,因爲您參考字段而不是

0

我也使用常量的結構,但只用於內部使用,不適用於公共API。因爲枚舉也轉換爲結構,所以感覺很自然。

5

這聽起來像你正在尋找一個資源文件(.resx)。這是一個體面的地方來存儲這樣的字符串,並且將您的字符串抽象成.resx文件將使未來本地化您的應用程序更加容易。 MSDN頁面http://msdn.microsoft.com/en-us/library/1ztca10y.aspx是一個體面的開始獲取更多信息。

5

不要忘記建議結構大小應該是大約16個字節。給定一個32位系統,那就是4個System.String引用。如果字符串的數量增加,我會說你最好用靜態類。

+0

好點。我記得早些時候讀過這篇文章,但很久沒有付諸實踐,因爲我的大部分代碼似乎都不適用於結構:-) – 2010-02-08 19:05:37

9

簡單的經驗法則:直到沒有其他選擇時才使用結構。

常量有幾個缺點:

  • 僅簡單類型都可以使用(字符串,數字等)
  • 常數被注入到參考集。如果用常量編譯程序集,並且不重新編譯使用常量組裝,你會惹上麻煩

我會寫你這樣的代碼(注意:重命名重構太):

public static class KnownNames 
{ 
    public static readonly string VeryLong = "Very Long Name"; 
    public static readonly string AnotherVeryLong = "Another Very Long Name"; 
    public static readonly string TheLastVeryLong = "The Last Very Long Name"; 
} 
+2

請注意解釋爲什麼使用'static readonly'而不是const? Const將被編譯時評估,這對於預期的用途來說是很好的。 – 2010-02-08 18:38:59

+2

我列出了const的缺點:只有簡單的類型和編譯的值。使用const如果你100%確定它不會改變(比如Math.Pi) – 2010-02-08 19:28:14

+1

我明白你的觀點,謝謝你的闡述。我不指望值會改變,但你永遠不知道誰決定改變他無盡的智慧值;-) – 2010-02-08 19:45:34

1

靜上課似乎是最好的方式,因爲這是最標準的和預期的。我認爲struct/const版本可能會更快,但經過一些測試後,它們不是。

下面是我的快速測試結果,包括長度,比較,concat,複製,indexOf和子串。它在沒有附加調試器的情況下在.Net 4.0中運行。

          .Net 3.0 .Net 4.0 
static class with static read-only string: 0.217 0.364 seconds 
static class with const   string: 0.211 0.361 seconds 
struct  with static read-only string: 0.211 0.372 seconds 
struct  with const   string: 0.214 0.371 seconds 
Properties.Resources    string: 1.173 1.268 seconds 

除了使用較慢的資源文件時,它們都具有相同的性能。雖然Properties.Resources較慢,但它不存儲在可執行文件中,因此在某些情況下可能更合適。因此,在我看來,使用「靜態類」或存儲字符串的Properties.Resources。

1

除非結構符合this answer中詳述的某些標準,否則通常會避免使用結構。

由於你的同事沒有使用它來存儲一個值,他應該使用一個類,而不是一個結構。

0

一個簡單的事實,你可以創建一個新的對象,是一個常數是通常不好的實踐的明顯證據。我說「通常」,因爲.NET確實偶爾使用這個概念,儘管它不清楚爲什麼。

當然,你總是可以做這樣的東西:

public class Foo 
{ 
    public struct Bar 
    { 
     public static double A = 100; 

     public Bar(double a) 
     { 
      A = a; 
     } 
    } 
} 

這也證明在技術上的Bar創造;然而,不能保證恆定的Bar將永遠是相同的(即使在單線程環境中)並且最終幾乎沒有用處。