【问题标题】:Create property object on demand or in constructor?按需或在构造函数中创建属性对象?
【发布时间】:2012-07-25 13:56:28
【问题描述】:

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

例如,我有 UserData 类型的属性,我可以对其进行初始化:

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

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

    private UserData _user = new UserData()

我发现了几个类似的线程:
Create an object in the constructor or at top of the class
C# member variable initialization; best practice?

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

你能告诉我什么是最好的选择吗?第二个选择可以解决什么问题?

【问题讨论】:

  • 我会假设第二个选项不是线程安全的。

标签: c# .net properties


【解决方案1】:

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

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

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

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

【讨论】:

  • 另一个区别是开发人员维护。如果创建了多个构造函数,则选项 1 是“按惯例”。选项 3 确保无论构造函数的数量如何都设置该字段。
【解决方案2】:

如果您只是使用纯数据,则首选在其定义处初始化支持字段(如果可能):

// 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&lt;T&gt; 的构造函数包含可以满足您的线程安全需求的重载:

  • None:多线程访问是“未定义行为”
  • PublicationOnly:第一个完成初始化的线程“获胜”
  • ExecutionAndPublication:锁保证只有一个线程初始化值

【讨论】:

    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 2015-03-24
      • 2019-07-11
      • 1970-01-01
      • 2018-06-11
      • 1970-01-01
      • 2016-07-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-22
      相关资源
      最近更新 更多