簡體   English   中英

按需還是在構造函數中創建屬性對象?

[英]Create property object on demand or in constructor?

在C#中初始化沒有設置方法的屬性的對象的最佳方法是什么?

例如,我具有UserData類型的屬性,可以對其進行初始化:

  1. 在構造函數中
  2. 吸氣劑

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

    private UserData _user = new UserData()

我發現了一些相似的線程:
在構造函數中或類的頂部創建一個對象
C#成員變量初始化; 最佳實踐?

但這是第一種和第三種選擇之間的考慮-沒有人考慮第二種選擇-你知道嗎? 從某個時候開始,我傾向於選擇獲取對象,但是我想知道是否存在一些我不知道的缺點。

您能告訴我什么是最好的選擇,什么問題可以利用第二個選擇?

這完全取決於您要使用它的方式,因此有明確的答案。

1 + 3與2之間的差異之一是可預測性。
使用1 + 3,您可以確切地知道在哪里創建對象以及在實例化類時的哪個點。 在某些情況下,這可能是理想的。
使用2,您需要依靠外部影響力(誰當時訪問屬性)來初始化字段。

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

如果UserData的創建花費大量時間,例如,當您不得不查詢數據庫時,您可能希望將其創建延遲到真正需要的時候。 包含UserData對象的對象構造得更快,因為它不需要等待UserData對象的創建。 如果不總是訪問該屬性,您甚至可以完全避免創建UserData實例。

如果僅使用普通數據,則最好在其定義處初始化后備字段(如果可能):

// 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 :鎖確保只有一個線程初始化該值

#2的一個問題是,如果該屬性可以被多個線程訪問,則可能會創建UserData對象的兩個副本。 #2的另外一個考慮因素是,如果UserData的創建成本很高,則您將在訪問屬性時(而不是在創建包含對象時)承擔創建該對象的費用。 根據您的用例,這可能是理想的,也可能不是理想的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM