60

In the C# 6, you can can simplify implementing a property by using a getter-only auto property. For example, if I were implementing the abstract Stream class:

public override bool CanRead { get; } = true;

However I can also write it with an expression body, also new in C# 6:

public override bool CanRead => true;

What is the difference between the two, and when should I use one or the other?

vcsjones
  • 138,677
  • 31
  • 291
  • 286

2 Answers2

69

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.

vcsjones
  • 138,677
  • 31
  • 291
  • 286
  • 1
    Technically in the first case isn't the generated backing field also `readonly`? – Kyle Jan 12 '15 at 21:41
  • 7
    The backing field is assigned as if it were assigned in the field initializer, not in the body of the constructor. You can observe this difference if the base class calls a virtual method, which occurs before the constructor body executes. It's a subtle difference, admittedly :) – Jon Skeet Jan 12 '15 at 21:46
  • 1
    @JonSkeet Oh you are right, the field is `initonly`. – vcsjones Jan 12 '15 at 21:53
  • 2
    @vcsjones: Yes, although that doesn't *stop* it from being assigned in the constructor body (that's a more common use in my experience). It's just the timing that's different. – Jon Skeet Jan 12 '15 at 21:54
4

In the case you describe in our example, I used to prefer:

public override bool CanRead { get; } = true;

But today I notified that this implementation cause a memory allocation for the backing field. And so, this implementation: bool CanRead => true; can save 4 bytes.

Orace
  • 7,822
  • 30
  • 45