2012-07-25 166 views
-1

在C#中沒有setter的情況下爲屬性初始化對象的最佳方法是什麼?按需或在構造函數中創建屬性對象?

例如,我有類型的UserData的屬性,我可以初始化:

  1. 在構造
  2. 在吸氣

    private UserData _user; 
    
    public UserData User 
    { 
        get 
        { 
         return _user?? (_user= new UserData()); 
        } 
    } 
    
  3. 初始化字段:

    private UserData _user = new UserData()

我發現幾個similiar主題:
Create an object in the constructor or at top of the class
C# member variable initialization; best practice?

但它是第一個和第三個選項之間的考慮 - 沒人想着第二個選項 - 你知道的方式?從某個時候起,我喜歡獲取對象,但我想知道是否有一些我不知道的缺點。

你能告訴我什麼是最好的選擇,什麼問題可以使用第二個選項?

+1

我會假設第二個選項不是線程安全的。 – Henrik 2012-07-25 14:11:13

回答

3

這一切都取決於你想用它做什麼,所以有明確的答案。

1 + 3和2之間的一個區別是可預測性。
使用1 + 3,您確切知道您的對象在哪裏創建,以及在您的類的實例化過程中的哪個點。在某些情況下這可能是可取的。
對於2,您依賴於外部影響(誰訪問屬性在哪個時間)來初始化該字段。

通過方法2中的延遲創建(僅在需要時才創建對象),您可以在創建包含類的對象時節省一些時間。

如果UserData的創建需要很長時間,例如,當您必須爲其查詢數據庫時,您可能需要延遲其創建,直到真正需要爲止。包含對象UserData的對象構建得更快,因爲它不需要等待創建對象UserData。如果該屬性不總是被訪問,你甚至可以完全避免創建一個UserData實例。

+0

另一個區別是開發人員維護。如果創建了多個構造函數,則選項1是「按約定」。選項3確保無論構造函數的數量如何,字段都被設置。 – user7116 2012-07-25 14:21:48

0

如果你只是使用普通的數據,初始化支持字段在其定義(如果可能的話)是首選:

// when you create constructor N+1, no worries about forgetting to set the value 
private UserData _userData = new UserData(); 

public UserData User 
{ 
    get { return _userData; } 
} 

如果您需要初始化被推遲,你最好的選擇是使用Lazy<T>

private Lazy<UserData> _userData = new Lazy<UserData>(() => new UserData()); 

public UserData User 
{ 
    get { return _userData.Value; } 
}  

Lazy<T>構造包含重載,它們可以解決你的線程安全的需求:

  • None:從多個線程訪問是「不確定的行爲」
  • PublicationOnly:第一個線程來完成初始化「奪」
  • ExecutionAndPublication:鎖保證只有一個線程初始化值
0

一個問題與# 2是如果該屬性可以被多個線程訪問,你可能會創建兩個UserData對象的副本。 #2的額外考慮是如果UserData創建成本昂貴,則將支付在訪問該屬性時創建該對象的成本,而不是在創建包含對象時支付該成本。取決於您的使用情況,這可能會也可能不會。

相關問題