-1

在 C# 中为没有设置器的属性初始化对象的最佳方法是什么?

例如,我有 UserData 类型的属性,我可以初始化它:

  1. 在构造函数中
  2. 在吸气剂中

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

    private UserData _user = new UserData()

我发现很少有类似的线程:
在构造函数中创建对象或在类
C# 成员变量初始化的顶部;最佳实践?

但这是第一个和第三个选项之间的考虑 - 没有人考虑第二个选项 - 你知道吗?一段时间以来,获取对象是我的首选,但我想知道是否有一些我不知道的缺点。

你能告诉我什么是最好的选择,什么问题可以利用第二个选项?

4

3 回答 3

3

这完全取决于你想用它做什么,所以有明确的答案。

1+3 和 2 之间的一个区别是可预测性。
使用 1+3,您可以准确地知道创建对象的位置以及类实例化的时间点。在某些情况下,这可能是可取的。
使用 2,您依赖外部影响(谁在何时访问该属性)来初始化该字段。

通过方法 2 中的延迟创建(仅在需要时创建对象),您可以在创建包含类的对象时节省一些时间。

如果UserData的创建需要很长时间,例如,当您必须为它查询数据库时,您可能希望将其创建延迟到真正需要时。包含对象的UserData对象构造得更快,因为它不需要等待UserData对象被创建。如果不总是访问该属性,您甚至可以完全避免创建UserData实例。

于 2012-07-25T14:08:57.687 回答
0

#2 的一个问题是,如果该属性可以被多个线程访问,那么您可能会创建 UserData 对象的两个副本。#2 的另一个考虑因素是,如果 UserData 的创建成本很高,您将在访问属性时而不是在创建包含对象时支付创建该对象的成本。根据您的用例,这可能需要也可能不需要。

于 2012-07-25T14:42:17.247 回答
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: 锁确保只有一个线程初始化值
于 2012-07-25T14:17:32.463 回答