c# 6自动属性-读取一次或每次

本文关键字:一次 读取 属性 | 更新日期: 2023-09-27 18:08:23

在设置某些属性时,我遵循一种模式,即检查相应的字段是否为空,如果不是,则返回该字段,如果是,则设置该字段。例如,我经常使用它来读取配置设置,以便延迟读取设置,并且只读取一次。下面是一个例子:

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

我已经开始使用c# 6的自动属性初始化,因为它确实清理并使我的代码更简洁。我想这样做:

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

但我不确定编译器如何解释它在这种情况下。这将有相同的效果,我的第一个代码块,设置(自动实现)字段一次,然后从字段读取?还是每次我得到DatabaseId时它都叫CloudConfigurationManager

c# 6自动属性-读取一次或每次

显示内容:

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

是一个"自动属性初始化器",关键字是"初始化器",来自MSDN博客:c#:新的和改进的c# 6.0:

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

初始化器每个实例运行一次(对于静态成员,每个类型运行一次)。参见c#语言规范,10.4.5变量初始化式:

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

代码编译成这样:

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");
    }       
}

当类型没有静态构造函数时,"静态字段初始化器在该类的静态字段首次使用之前,在与实现相关的时间执行"。

c# 6.0 readonly auto property将创建一个字段并只调用一次初始化器。

然而,这并不等于你得到的。在您的代码中,CloudConfigurationManager.GetSetting将仅在有人读取DatabaseId属性时被调用,但是具有"只读自动属性"的CloudConfigurationManager.GetSetting将在类初始化时被调用。

这个差异可能/可能无关紧要。视情况而定。如果调用是昂贵的,那么你可以使用Lazy<T>,这大致等于你所拥有的。

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

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

然而,第二个例子将把空字符串视为有效值并保留它。

第一个代码:

if(id == null || id == "") // Get ID from settings
第二代码:

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

auto-property自动拥有一个后备字段。在这种情况下,该字段只能从构造函数或自动属性初始化器中赋值。你的新代码比第一个更好。它只会对CloudConfigurationManager.GetSetting("database");进行一次调用。在第一个示例中,必须在每次调用属性get时进行检查。