2010-01-22 45 views
10

我最近發現了一些關於汽車性能的東西,並且非常喜歡它們。在這一刻,我正試圖在任何可能的地方使用它們。不是真的能夠在任何地方使用它們,而是更多地瞭解它們在大多數情況下的工作情況。正在實現一個使用自動屬性的單例是一個好主意嗎?

現在我正在做一個單身人士,並認爲:「嘿,讓我們在這裏嘗試自動屬性」。

public class MySingleton 
{ 
    public static MySingleton MySingleton { get; private set; } 

    private MySingleton() {} 

    static MySingleton() { MySingleton = new MySingleton(); } 
} 

所以我的問題是:「這是一個好主意,實現這樣的單身人士嗎?」

我不問一個單身人士是否是個好主意。

回答

14

我不會親自這樣做。我不喜歡使用自己實現的屬性與私人setter,你永遠不會調用真的你想要一個只讀屬性支持一個只讀變量。這只是一個更多的代碼行更明確的瞭解你的意思:

public sealed class MySingleton 
{ 
    private static readonly MySingleton mySingleton; 
    public static MySingleton MySingleton { get { return mySingleton; } } 

    private MySingleton() {} 

    static MySingleton() { mySingleton = new MySingleton(); } 
} 

這樣,沒有一個人甚至誘惑改變單級重新分配財產,或變量,因爲編譯器阻止他們。他們必須添加一個setter和/或使變量非只讀,這是一個更大的變化 - 希望他們能夠重新考慮。

換句話說:

  • 是的,它會工作。
  • 不,我不認爲這是個好主意。

作爲C#6,這是具有隻讀雖然自動實現的屬性容易:

public sealed class MySingleton 
{ 
    public static MySingleton MySingleton { get; } = new MySingleton();  
    private MySingleton() {}   
    static MySingleton() {} 
} 
+0

我強烈反對。發明了自動屬性以使代碼更加簡潔,這使得代碼更具可讀性。恕我直言,對於其他人來說,讓自己的設計搞砸更難一些。 – 2010-01-22 13:17:16

+6

@Philippe:自動屬性是爲了使代碼更簡潔而發明的,其中替換代碼等同於原始*。這裏沒有這樣的等價關係:即使它有一個私有的setter,你用一個只讀屬性替換一個只讀屬性。這可能看起來微不足道,但我更喜歡我的代碼來表達我的意圖 - 我的意圖是隻能將該值設置一次。自動實現的屬性表達了不同的意圖。 – 2010-01-22 13:24:55

+0

對於二傳手的「意圖」,你有一點意見,但最終對於這個階級的消費者來說,沒有任何區別。具有私人支付者的自動特性非常類似於具有私人支持字段的只讀特性。當然,它會編譯成不同的代碼,但從類的消費者的角度來看,它本質上是相同的。現在我必須自己拍,因爲我從來沒有喜歡過自動屬性,現在我正在捍衛它的使用(但這是我猜想的另一個問題的主題) – 2010-01-22 13:41:23

1

我看不出有什麼理由不正確。畢竟,自動屬性只是私有(編譯器生成的)後臺字段的訪問器的語法糖。

0

當然,我沒有看到任何問題。

3

請參閱this關於如何正確實現單身人士。

你知道單身人士是邪惡的,對嗎?

+0

+1實施單身人士的最佳方式:使用DI容器,並將類型設置爲單身作用域。 – 2010-01-22 12:51:32

+6

「我不問一個單身人士是否是個好主意。」 – 2010-01-22 12:52:09

+0

問題也得到了解答,你的博客上有道具。 – 2010-01-22 12:55:00

8

我會從除喬恩一個稍微不同的方向接近此。 無論對象是否爲單例,在邏輯上是否最適合作爲屬性建模?

屬性應該表示...屬性。 (上尉明顯地再次擊中!)你知道。顏色。長度。高度。名稱。家長。所有的東西,你會邏輯上認爲是一個東西的財產。

我不能想象財產的一個對象,這是一個邏輯上單身。也許你想出了一個我沒有想到的情景;今天早上我還沒有任何飲食博士胡椒。但我懷疑這是對模型語義的濫用。

你能描述一下這個單身人士嗎?爲什麼你認爲它是某物的屬性?

所有這一切,我自己經常使用這種模式;通常是這樣的:

​​

邏輯上「空」邏輯上是一個不可變堆棧的屬性?不可以。在這裏能夠說出令人信服的好處:

var stack = ImmutableStack<int>.Empty; 

勝過我對屬性在邏輯上屬性的渴望。說

var stack = ImmutableStack<int>.GetEmpty(); 

看起來很奇怪。

在這種情況下,擁有隻讀字段和常規屬性,還是靜態ctor和自動駕駛儀在這種情況下更好,似乎不像是否首先將其作爲屬性這樣一個有趣的問題。在一種「純粹主義」的情緒中,我可能會與喬恩站在一起,讓它成爲只讀領域。但我也經常使用這種模式,使用私人定位器爲邏輯上不變的物體制作自動座駕,只是出於懶惰。

問題的各個方面都如何?

+0

嗯,有趣。我從來沒有真正以這種方式考慮過財產。對我來說,他們一直是取代器方法的替代品。在某種程度上,我將訪問器方法視爲改善公共領域的一種方式(部分隱藏,放入界面,添加一些檢查信息)。然後屬性能夠比getter和setter更加直觀。所以對於我來說,一個財產從來不必在邏輯上成爲這個類所代表的東西的財產。對我來說,一個物業就是從外面看場地的樣子。 – 2010-01-22 19:17:05

+0

您能否詳細說明'ImmutableStack .Empty'示例中屬性類語法的好處?我想更好地理解你在這裏獲得的好處,特別是在LINQ中'Enumerable.Empty ()'類似於你在這個例子中避免的語法類型。 – LBushkin 2010-01-22 22:30:12

+0

@LBushkin - 我想「空」vs「空()」與「GetEmpty()」都是非常小的差異。我認爲「引人注目的好處」是誇張的! :-) – 2010-01-23 15:07:19

0

汽車物業?不,我不會在單身人士身上使用二傳手,是的,我做過。我想你想要更多的控制權,而不是汽車財產會給你。

...建設性的反饋是歡迎在這裏,請。這感覺像一個勇敢的(或愚蠢的)在這個尊敬的公司的舉動...

我的情況,一個WPF應用程序,有一個當前項目比可以加載和保存。目前的項目設置上被廣泛使用的應用程序...

    在WPF綁定
  • 的UI,使用戶可以更改設置,因此INotifyPropertyChanged接口。
  • 我也使用Fody.PropertyChanged但不做靜態屬性更改,因此NotifyStaticPropertyChanged
  • INotifyPropertyChanged與單身人士的屬性上WPF綁定工作正常。
  • Settings的一個實例是使用JSON.NET [de]序列化的,因此單例中的屬性爲[JsonIgnore]。我在將它加載到單例或將其保存到磁盤之前進行驗證。
  • 記錄器是Serilog。你記錄的東西,對吧?
  • 單身人士是publicpublic獲得者,因爲WPF綁定僅適用於公共屬性。 internal setter不會影響它。 Settings的所有屬性公開爲WPF綁定。

我在代碼中留下了所有「噪音」,因爲有些人可能會覺得它很有用。

class Settings : INotifyPropertyChanged 
{ 
    private static Settings _currentSettings = new Settings(); 

    /// <summary> The one and only Current Settings that is the current Project. </summary> 
    [JsonIgnore] // so it isn't serialized by JSON.NET 
    public static Settings CurrentSettings // http://csharpindepth.com/Articles/General/Singleton.aspx 
    { 
     get { return _currentSettings; } 

     // setter is to load new settings into the current settings (using JSON.NET). Hey, it works. Probably not thread-safe. 
     internal set 
     { 
      Log.Verbose("CurrentSettings was reset. Project Name: {projectName}", value.ProjectName); 
      _currentSettings = value; 
      _currentSettings.IsChanged = false; 
      NotifyStaticPropertyChanged("CurrentSettings"); 
     } 
    } 

    // http://10rem.net/blog/2011/11/29/wpf-45-binding-and-change-notification-for-static-properties 
    /// <summary> Fires when the Curent CurrentTvCadSettings is loaded with new settings 
    ///   Event queue for all listeners interested in StaticPropertyChanged events. </summary> 
    public static event EventHandler<PropertyChangedEventArgs> StaticPropertyChanged = delegate { }; 
    private static void NotifyStaticPropertyChanged(string propertyName) 
    { 
     StaticPropertyChanged?.Invoke(null, new PropertyChangedEventArgs(propertyName)); 
    } 

    // various instance properties including .... 

    public string ProjectName {get; set;} 

    [JsonIgnore] 
    public bool IsChanged { get; set; } 
} 

使用的單設爲一個新加載的項目,settings簡直是

Settings settings = new Settings(); 
// load, save, deserialize, set properties, go nuts 
Settings.CurrentSettings = settings; 

setter方法可能不是線程安全的,但我只能從UI線程設置在一個位置,我不怕。你可以讓它線程安全,因爲http://csharpindepth.com/Articles/General/Singleton.aspx

我意識到OP沒有問WPF,但我認爲它是相關的,以顯示爲什麼你可能想設置一個單身人士。我做到了,因爲這是最簡單的解決方案。

相關問題