C#6自动属性 ​​- 读一次还是每次?

时间:2015-08-17 13:43:20

标签: c# automatic-properties c#-6.0

我在设置某些属性时遵循一个模式,我检查相应的字段是否为空,如果没有则返回该字段,如果是,则设置它。例如,我经常使用它来读取配置设置,以便懒惰地读取设置,以便只读取一次。这是一个例子:

private string DatabaseId
{
    get
    {
        if (string.IsNullOrEmpty(databaseId))
        {
            databaseId = CloudConfigurationManager.GetSetting("database");
        }

        return databaseId;
    }
}

我已经开始使用C#6 autoproperty初始化,因为它真正清理并使我​​的代码更简洁。我想做这样的事情:

private string DatabaseId { get; } = CloudConfigurationManager.GetSetting("database");

但我不确定编译器在这种情况下如何解释它。这是否与我的第一个代码块具有相同的效果,设置(自动实现)字段一次,然后从字段中读取?或者,每次收到CloudConfigurationManager时,这会调用DatabaseId吗?

4 个答案:

答案 0 :(得分:13)

你展示的内容:

private string DatabaseId { get; } = CloudConfigurationManager.GetSetting("database");

来自MSDN Blogs: C# : The New and Improved C# 6.0的“自动属性初始化程序”,关键字为“初始化程序”:

  

auto-property初始化程序允许直接在其声明中分配属性。对于只读属性,它负责确保属性不可变所需的所有仪式。

初始化程序每个实例运行一次(或静态成员每种类型运行一次)。见C# Language Specification, 10.4.5 Variable initializers

  

对于实例字段,变量初始值设定项对应于在创建类的实例时执行的赋值语句。

所以代码编译成这样的东西:

public class ContainingClass
{
    private readonly string _databaseId;
    public string DatabaseId { get { return _databaseId; } }

    public ContainingClass()
    {
        _databaseId = CloudConfigurationManager.GetSetting("database");
    }       
}

对于静态变量,这种看起来是一样的:

private static string DatabaseId { get; } = CloudConfigurationManager.GetSetting("database");

编译为,或多或少:

public class ContainingClass
{
    private static readonly string _databaseId;
    public static string DatabaseId { get { return _databaseId; } }

    static ContainingClass()
    {
        _databaseId = CloudConfigurationManager.GetSetting("database");
    }       
}

虽然不完全,但是当类型没有静态构造函数时,“静态字段初始值设定项在首次使用该类的静态字段之前的实现相关时间执行”。

答案 1 :(得分:9)

C#6.0 readonly auto属性将创建一个字段并仅调用初始化程序一次。

然而,这并不等于你所拥有的。在您的代码中,CloudConfigurationManager.GetSetting仅在有人读取DatabaseId属性时调用,但在类初始化时将调用“readonly auto property”CloudConfigurationManager.GetSetting

这种差异可能/可能无关紧要。这取决于。如果通话费用昂贵,那么您可以使用Lazy<T>,这大致等于您所拥有的费用。

答案 2 :(得分:2)

它只会设置一次值,然后才读取它。

然而,在您现在不再拥有databaseId字段的意义上存在细微差别。在第一个示例中,您基本上检查id == null || id == ""以设置数据库字符串。这意味着如果您创建一个databaseId设置为空字符串的新实例,第一个示例仍将从设置中获取ID。

然而,第二个例子会将空字符串视为有效值并保留在其中。

第一个代码:

if(id == null || id == "") // Get ID from settings

第二段代码:

if(id == null) // Get ID from settings

答案 3 :(得分:1)

自动属性自动具有支持字段。在这种情况下,此字段只能从构造函数或自动属性初始值设定项中分配。您的新代码优于第一个代码。它只会拨打一次CloudConfigurationManager.GetSetting("database");。在第一个示例中,每次调用属性get时都必须进行检查。