Search code examples
c#automatic-propertiesc#-6.0

C# 6 auto-properties - read once or every time?


I follow a pattern when setting certain properties whereby I check to see if the corresponding field is empty, returning the field if not and setting it if so. I frequently use this for reading configuration settings, for example, so that the setting is read lazily and so that it is only read once. Here is an example:

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

        return databaseId;
    }
}

I have started to use C# 6 autoproperty initialization as it really cleans up and makes my code more concise. I would like to do something like this:

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

But I'm not sure how the compiler interprets it in this case. Will this have the same effect as my first block of code, setting the (automatically implemented) field once, and thereafter reading from the field? Or will this call the CloudConfigurationManager every time I get DatabaseId?


Solution

  • What you show:

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

    Is an "Auto-Property Initializer", keyword being "initializer", from MSDN Blogs: C# : The New and Improved C# 6.0:

    The auto-property initializer allows assignment of properties directly within their declaration. For read-only properties, it takes care of all the ceremony required to ensure the property is immutable.

    Initializers run once per instance (or once per type for static members). See C# Language Specification, 10.4.5 Variable initializers:

    For instance fields, variable initializers correspond to assignment statements that are executed when an instance of the class is created.

    So that code compiles to something like this:

    public class ContainingClass
    {
        private readonly string _databaseId;
        public string DatabaseId { get { return _databaseId; } }
    
        public ContainingClass()
        {
            _databaseId = CloudConfigurationManager.GetSetting("database");
        }       
    }
    

    For static variables, this kind of looks the same:

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

    Compiles to, more or less:

    public class ContainingClass
    {
        private static readonly string _databaseId;
        public static string DatabaseId { get { return _databaseId; } }
    
        static ContainingClass()
        {
            _databaseId = CloudConfigurationManager.GetSetting("database");
        }       
    }
    

    Though not entirely, as when the type doesn't have a static constructor, "static field initializers are executed at an implementation-dependent time prior to the first use of a static field of that class".