Search code examples
c#c#-6.0automatic-properties

Read-Only Auto-Property for Simple Types: Initializer VS Expression Body Getter


In C# 6.0, the new syntax let us write read-only auto-properties with using an initializer:

public bool AllowsDuplicates { get; } = true;

Likewise, we can write it using an expression body getter:

public bool AllowsDuplicates => true;

For simple types, these two should have the same effect: a read-only auto-property that returns true.

But is one of them preferred over the other? I suspect that the former uses a backing field:

private readonly bool _backingField = true;
public bool AllowsDuplicates {
    get {
        return _backingField;
    }
}

Whereas the latter is turned into something like:

public bool AllowsDuplicates {
    get {
        return true;
    }
}

Is that right, or is the compiler smarter than this?


Solution

  • I suspect that the former uses a backing field

    The auto-property initializer does in fact creating a backing field! You can throw this in ILSpy and see it in the output:

    public class One
    {
        public bool AllowsDuplicates
        {
            [CompilerGenerated]
            get
            {
                return this.<AllowsDuplicates>k__BackingField;
            }
        }
    
        public One()
        {
            this.<AllowsDuplicates>k__BackingField = true;
            base..ctor();
        }
    }
    
    public class Two
    {
        public bool AllowsDuplicates
        {
            get
            {
                return true;
            }
        }
    }
    

    But is one of them preferred over the other?

    For the specific example in the question, the auto-property would allow a constructor to ask for a bool and assign it. The second style would not. If the intent is to use it as a "default value" which can be modified once during construction, then an auto-property is the right choice.

    class Test
    {
        // Could assign this in the second constructor
        public bool AllowsDuplicates { get; } = true;
    
        // Cannot assign this in the second constructor
        public bool AllowsDuplicates => true;
    
        public Test()
        {
            // Default value used
        }
    
        public Test(bool value)
        {
            AllowsDuplicates = value;
        }
    }
    

    I've seen expression bodied syntax win out most when it's a cover for a small function that is utilized as a property. A struct in Eric Lippert's dedoublifier has a nice example of this:

    public DoubleHelper(double d)
    {
        this.RawBits = (ulong)BitConverter.DoubleToInt64Bits(d);
    }
    
    public ulong RawBits { get; }
    // RawSign is 1 if zero or negative, 0 if zero or positive
    public int RawSign => (int)(RawBits >> 63);
    public int RawExponent => (int)(RawBits >> 52) & 0x7FF;
    public long RawMantissa => (long)(RawBits & 0x000FFFFFFFFFFFFF);
    public bool IsNaN => RawExponent == 0x7ff && RawMantissa != 0;
    public bool IsInfinity => RawExponent == 0x7ff && RawMantissa == 0;
    public bool IsZero => RawExponent == 0 && RawMantissa == 0;
    public bool IsDenormal => RawExponent == 0 && RawMantissa != 0;
    

    There's one value which is assigned in the constructor, and the rest are property values which are computed based off of it.