C# 按需或在构造函数中创建属性对象?

C# 按需或在构造函数中创建属性对象?,c#,.net,properties,C#,.net,Properties,在C#中初始化属性对象而不使用setter的最佳方法是什么 例如,我有UserData类型的属性,可以对其进行初始化: 在构造函数中 内吸气剂 private UserData _user; public UserData User { get { return _user?? (_user= new UserData ()); } } 初始化字段: private UserData\u user=new UserData()

在C#中初始化属性对象而不使用setter的最佳方法是什么

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

  • 在构造函数中
  • 内吸气剂

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

    private UserData\u user=new UserData()

  • 我发现很少有类似的线索:

    但这是第一个和第三个选择之间的考虑——并没有人考虑第二个选择——你们知道这条路吗?从某个时候起,获取对象是我的首选选项,但我想知道是否有一些缺点我不知道


    你能告诉我什么是最好的选择,第二种选择会带来什么问题吗?

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

    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; }
    }
    
    如果需要延迟初始化,最好的选择是使用:

    private Lazy _userData=new Lazy(()=>new userData());
    公共用户数据用户
    {
    获取{return\u userData.Value;}
    }    
    
    Lazy
    的构造函数包含可以满足线程安全需求的重载:

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

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

    我假设第二个选项不是线程安全的。另一个区别是开发人员维护。如果创建了多个构造函数,则选项1是“按约定”。选项3确保字段的设置与构造函数的数量无关。
    private Lazy<UserData> _userData = new Lazy<UserData>(() => new UserData());
    
    public UserData User
    {
        get { return _userData.Value; }
    }