2013-02-14 148 views
2

我有一些字典對象在應用程序的生命週期中不會改變。我打算使用靜態只讀變量,任何人都可以提供以下幾點的輸入。直接初始化爲靜態只讀屬性和靜態特性與GET運營商之間靜態只讀變量初始化

  1. 差異備份與私人只讀靜態變量。

  2. 使用它們是否有任何風險,因爲我在線閱讀不使用public static變量。這是否適用於這種情況。

回答

3

我有一個在應用程序生命週期並沒有改變一些字典對象。

當您標記字典類型readonly的變量時,會阻止替換您使用另一個字典分配的字典。你做使該字典只讀的,在這個意義上,只要呼叫者得到他的手在那本字典,他是免費的,他想,擦乾淨,或設置不正確的值的任何方式改變(由錯誤,毫無疑問)。如果您需要將Dictionary設置爲只讀,請考慮借用只讀封裝的實現from this answer

一般來說,在變量頂部添加屬性或者在{get;private set;}自動屬性上添加屬性的優勢在於您可以在setter中執行額外的檢查,或者在getter中添加一些代碼(比如說,收集訪問統計信息或記錄日誌)。通過思考來訪問這個領域也是有意義的。它看起來並不像你正在做的那樣,所以暴露只讀變量聽起來合適,並且不會帶來額外的風險。

編輯:(上使用反射)當通過反射訪問對象數據,則必須如果正在訪問屬性Xyz或場Xyz指定。相反,當你編寫一個C#程序時,你編寫了SomeClass.Xyz,編譯器會判斷它是否屬於你的屬性或字段。如果您創建一個公開場Xyz一類,後來決定用性能Xyz來取代它,重新編譯指Xyz直接是所有需要的代碼。但是,如果您編寫了一些通過反射API訪問Xyz的代碼,則需要重寫該代碼,因爲編譯器無法爲您捕獲更改。

+0

它幫助!我不明白這裏的反思,這也是Oded提到的。儘管我可能不會使用它,請您提供更多信息。 – Sunny 2013-02-14 22:28:11

+0

@Sundeep我編輯了答案,以擴大反思含義。 – dasblinkenlight 2013-02-14 22:38:49

1

因爲,作爲字段,它們不能被靜態構造函數運行後發生變化,存在不變性和線程安全性方面沒有任何理由在其靜態只讀屬性包裝他們。

但是請注意,該過字段性質有時需要 - 數據綁定是一個例子,由於是採用反射的(其中,如果標準化上的一個或另一個,可能更容易)。

1

我推薦使用性能儘可能。沒有真正的表現懲罰,這是公共領域最經常提到的原因。主要好處是您可以避免將來的實施細節更改。如果你在現場工作,你的編譯呼叫者每次都會被綁定到一個字段。

1

公共靜態只讀字段和公共靜態屬性之間幾乎沒有區別。該屬性確實在一定程度上保護了訪問權限,但如果你所做的只是返回值,那麼這兩者並沒有什麼不同。

// access between these two is almost identical 
public class Foo 
{ 
    public readonly static IDictionary<string, int> bar = 
     new Dictionary<string, int>(); 
    public static IDictionary<string, int> Bar 
    { 
     get { return bar; } 
    } 
} 

你要碰到的問題是,即使該領域已被標記爲readonly它仍然是可變的。什麼是阻止某人撥打Foo.Bar.Clear();爲了解決這個問題,您可以創建一個副本並將其返回,或者您可以使用只讀字典實現。

public class Foo 
{ 
    private readonly static IDictionary<string, int> bar = 
     new Dictionary<string, int>(); 
    public static IDictionary<string, int> Bar 
    { 
     // now any calls like Foo.Bar.Clear(); will not clear Foo.bar 
     get { return new Dictionary<string, int>(bar); } 
    } 
} 

然後,如果你,如果你確實需要添加或刪除Foo.Bar您可以創建功能來限制潛在的對象是如何修改的項目。

public static void AddItem(string key, int value) 
{ } 
public static void RemoveItem(string key) 
{ } 

即使你使用ReadonlyDictionary實現,你可能仍然會碰到的問題與修改,如果TKey或字典的TValue是可變的。

總的來說,你已經看到避免公共靜態變量的原因在這裏仍然適用。您正在引入一個靜態依賴關係,只要使用Foo.Bar的代碼被重用,該依賴關係就會被拖動。除非您正在靜態訪問的對象不可變以及只讀,否則可能會出現一些無法預料的副作用。

如果在組合根創建對象的單個實例並將其傳遞給需要依賴關係的對象,那麼最好使用它。

public void CompRoot() 
{ 
    var bar = new ReadonlyDictionary(
     ... initialize with desired values ... 
      // also this object is not in .NET but there 
      // are many available on the net 
    ); 

    var obj = new UsesBarDependency(bar); 
} 

public class UsesBarDependency 
{ 
    private readonly ReadonlyDictionary bar; 

    public UsesBarDependency(ReadonlyDictionary bar) 
    { 
      if (bar == null) 
       throw new ArgumentNullException("bar"); 
      this.bar = bar; 
    } 

    public void Func() 
    { 
     // use to access the dependency 
     this.bar 
     // over 
     Foo.Bar 
    } 
} 

這樣做允許的UsesBarDependency用戶提供任何ReadonlyDictionary的對象,而不是被迫使用靜態Foo.Bar依賴。