Differencebetween Getter-Only Auto Properties and Expression Body Properties

What is the difference between getter-only auto properties and expression body properties?

They are syntactic sugar for two different things. The former initializes a backing field, and sets it to the expression on the right hand side of the assignment during field initialization. The latter creates a get that does exactly what is in the expression.

public override bool CanRead { get; } = true;

is equivalent to

private readonly bool __backingFieldCanRead = true;

public override bool CanRead
{
get
{
return __backingFieldCanRead;
}
}

This

public override bool CanRead => true;

is equivalent to

public override bool CanRead
{
get
{
return true;
}
}

They behave differently. The first case sets the value of the property when the object is created and the field are initialized, the other case evaluates the expression every time the property's getter is invoked. In the simple case of a bool, the behavior is the same. However if the expression causes side effects, things are different. Consider this example:

class Program
{
static void Main(string[] args)
{
var fooBar1 = new FooBar();
Console.WriteLine(fooBar1.Baz);
Console.WriteLine(fooBar1.Baz);
var fooBar2 = new FooBar();
Console.WriteLine(fooBar2.Baz);
Console.WriteLine(fooBar2.Baz);
}
}

public class FooBar
{
private static int counter;
public int Baz => counter++;
}

Here, "0, 1, 2, 3" are printed. The static counter field is incremented every time the property's getter is invoked. However, with a property initializer:

public int Baz { get; } = counter++;

Then "0, 0, 1, 1" is printed because the expression is evaluated in the object's constructor.

Difference between Expression-Bodied Properties and simple Getter Properties

You have two groups of constructs which are equivalent.

Group 1

When you don't need write access to the backing field outside the constructor, you can use any of these constructs:

private readonly int _x;
public int x => _x;

or

private readonly int _x;
public int x { get => _x; }

or

private readonly int _x;
public int x { get { return _x; } }

or

public int x { get; }

Group 2

When you need access to the backing field outside the constructor, you can use any of these constructs:

private int _x;
public int x => _x;

or

private int _x;
public int x { get => _x; }

or

private int _x;
public int x { get { return _x; } }

or

public int x { get; private set; }

You can expect all of the alternatives to be equally fast. In the last construct the compiler will inject a setter method (it will inject a backer field too, as for every automatic property). In the other cases you access the field directly. The injected setter will almost certainly be inlined by the jitter, which removes the performance penalty of a method call. Check this Q&A for details on JIT inlining.

The automatic property is certainly more concise, which makes your code neater, especially when you have many properties. But at the end of the day it comes down to personal preference (or your team's coding rules).

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

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.

Is there a difference between the following ways of using expression-bodied syntax in c#?

Both ways result in the same IL.

For

using System;
public class Program {
public DateTime MyDate1 { get => DateTime.UtcNow; }
public DateTime MyDate2 => DateTime.UtcNow;
public void Main() {
}
}

the abbreviated IL for both versions is (I used https://sharplab.io):

    // Methods
.method public hidebysig specialname
instance valuetype [mscorlib]System.DateTime get_MyDate1 () cil managed
{
// Method begins at RVA 0x2050
// Code size 6 (0x6)
.maxstack 8

IL_0000: call valuetype [mscorlib]System.DateTime [mscorlib]System.DateTime::get_UtcNow()
IL_0005: ret
} // end of method Program::get_MyDate1

.method public hidebysig specialname
instance valuetype [mscorlib]System.DateTime get_MyDate2 () cil managed
{
// Method begins at RVA 0x2050
// Code size 6 (0x6)
.maxstack 8

IL_0000: call valuetype [mscorlib]System.DateTime [mscorlib]System.DateTime::get_UtcNow()
IL_0005: ret
} // end of method Program::get_MyDate2

(...)

// Properties
.property instance valuetype [mscorlib]System.DateTime MyDate1()
{
.get instance valuetype [mscorlib]System.DateTime Program::get_MyDate1()
}
.property instance valuetype [mscorlib]System.DateTime MyDate2()
{
.get instance valuetype [mscorlib]System.DateTime Program::get_MyDate2()
}

What's the difference between defining properties with { } vs =?

It's only syntactic sugar.

public string PropertyA => throw new NotSupportedException();

and

public string PropertyB { get { throw new NotSupportedException(); } }

compile to the same byte-code.

The expression body is just a shorter way of making a read-only property.

I think it looks nicer in certain cases, but it's a style preference.

Auto-property overridden with expression body

First, a general note: if you are very interested in such matters, the quickest way to resolve it is to actually compile code, and then use a tool like ildasm or ILSpy (in IL mode) to look at the generated code. Obviously the result of this cannot be generalized to make definite statements about what the compiler should do or must do (that can only be answered by standards), but for "I wonder how" questions it often suffices.

Expression body properties are simply shorthand for writing out methods; they will never cause a backing field to be generated. BarPage could be written out in full like this:

public class BarPage : FooPage
{
protected override string PageName
{
get { return "FooBar"; }
}
}

This is irrespective of how the property is implemented in FooPage, and whether it has a backing field there or not. In your example, it does not, because this isn't an auto-property:

protected abstract string PageName { get; }

This is an abstract property, which existed before read-only auto-properties were introduced. It looks very much like an auto-property, but it isn't one. The following isn't legal C# syntax but reflects the IL translation better:

protected string PageName 
{
abstract get;
}

No backing field here. On the other hand, the following is a read-only auto-property and does have a backing field:

protected virtual string PageName { get; }

Imagine it looking like this (again, not legal C# syntax):

private readonly $PageNameBackingField;
protected string PageName
{
virtual get { return $PageNameBackingField; }
}

But, crucially, this still has no influence at all on the implementation in BarPage, because the getter there doesn't rely on the base implementation. If you referenced base.PageName explicitly, you would find that this works if the base property is virtual, and will give an error if the base property is abstract. You'd still not be accessing the backing field directly (which is good; insulating clients from the details about how the property is implemented is the whole point of properties).

Difference between (auto) properties initialization syntax in C# 6

Listing 3 is C# 6's equivalent of listing 2, where the backing field is provided under the hood.

Listing 4:

public List<string> Items => new List<string>();

is equivalent to:

public List<string> Items { get { return new List<string>(); } }

which as you can imagine returns a new empty list every time you access the property.

The difference between listings 2/3 and 4 is further explored in this Q&A with an example.

Listing 1 is just an auto property with a getter and a private setter. It's not a readonly property in that you can set it anywhere you can access any of the type's private members. A readonly property (that is, a getter-only property) can only be initialized either in a constructor or in the property declaration, much like a readonly field.

Difference in C# between different getter styles

Yes, both of them are read-only, but there is a difference. In the first one, there's a backing field which is initialized to 0 before the constructor is executed. You can change the value only in the constructor, just like a regular read-only field. The getter itself just returns the value of the field.

In the second one, the getter just returns 0 every time, with no field involved.

So to avoid using any automatically implemented properties or expression-bodied members at all, we have:

First version

private readonly int _number = 0;
public int Number { get { return _number; } }

Second version

public int Number { get { return 0; } }

A clearer example of the difference might be seen like this:

public DateTime CreationTime { get; } = DateTime.UtcNow;
public DateTime CurrentTime => DateTime.UtcNow;

If you create a single object, its CreationTime property will always give the same result - because it's stored in a readonly field, initialized on object construction. However, every time you access the CurrentTime property, that will cause DateTime.UtcNow to be evaluated, so you'll get a potentially different result.



Related Topics



Leave a reply



Submit