在C#中没有setter的情况下初始化属性对象的最佳方法是什么?
例如,我有UserData类型的属性,我可以初始化它:
在getter中
private UserData _user;
public UserData User
{
get
{
return _user?? (_user= new UserData ());
}
}
初始化字段:
private UserData _user = new UserData()
我发现几个类似的线程:
Create an object in the constructor or at top of the class
C# member variable initialization; best practice?
但是考虑第1和第3选项 - 没有人考虑第2选项 - 你知道吗?从某种程度上来说,获取对象是我的优先选择,但我想知道是否有一些我不知道的缺点。
你能告诉我什么是最好的选择,什么问题可以使用第二选项?
答案 0 :(得分:3)
这一切都取决于你想用它做什么,所以有明确的答案。
1 + 3和2之间的一个区别是可预测性 使用1 + 3,您可以确切地知道对象的创建位置以及在类实例化期间的哪个位置。在某些情况下这是可取的 使用2,您可以依赖外部影响(访问该属性的时间)来初始化字段。
使用方法2中的延迟创建(仅在需要时创建对象),可以在创建包含类的对象时节省一些时间。
如果UserData
的创建需要花费很多时间,例如,当您必须为数据库查询数据时,您可能希望将其创建延迟到必要时。包含UserData
对象的对象构造得更快,因为它不需要等待创建UserData
对象。如果不总是访问该属性,您甚至可能完全避免创建UserData
实例。
答案 1 :(得分: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
:完成初始化“wins”的第一个线程ExecutionAndPublication
:locks确保只有一个线程初始化值答案 2 :(得分:0)
#2的一个问题是,如果多个线程可以访问该属性,则可能会创建UserData对象的两个副本。 #2的另一个考虑因素是,如果创建UserData是昂贵的,那么在访问属性时将支付创建该对象的成本,而不是在创建包含对象时。根据您的使用情况,这可能是也可能不合适。