Difference in C# between different getter styles
Asked Answered
A

3

155

I do sometimes see abbreviations in properties for the getter. E.g. those two types:

public int Number { get; } = 0

public int Number => 0;

Can someone please tell me if there are any differences between those two. How do they behave? Are both of them read-only?

Agni answered 5/9, 2017 at 5:44 Comment(0)
M
265

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.

Marenmarena answered 5/9, 2017 at 5:46 Comment(1)
Do note that the second version does not always return the same value. One good example is if you return random.NextInt(). The first version will evaluate that once and always have the same value. The second will return a new value each time.Cacoepy
C
247

One difference is when that 0 is evaluated: at object creation or when the property is used.

You can see this better with DateTime properties:

class SomeTestClass
{
    public DateTime Start { get; } = DateTime.Now;

    public DateTime Now => DateTime.Now;
}

The Start property keeps returning the same time (of when the instance was created), while Now changes to reflect the current time.

Explanation:

The first version ("Start") supplies an initial value that may even be overwritten by the constructor. So this is evaluated just once.
The second version ("Now") provides the expression that will be the "getter" of this property. So this is evaluated every time the property is read. There isn't even a backing field that the constructor can overwrite.

Charmian answered 5/9, 2017 at 10:36 Comment(3)
This is the most important distinction I think.Suburbia
The accepted answer most precisely defines the difference in the example code, but this explains a more useful difference in the two structures.Tatyanatau
Wow, you got more up-votes than the famous Jon Skeet himself.Seditious
J
21

These are C# 6 language features.

First example

public int Number { get; } = 0

The first example is a getter-only auto property. The backing field of a getter-only auto-property is implicitly declared as readonly.

Second example

public int Number => 0;

And the second example is expression bodies on property-like function members. Note that there isn't any get keyword: It is implied by the use of the expression body syntax.

Both are readonly.

Jillian answered 5/9, 2017 at 5:48 Comment(3)
... but as Jon Skeet explains, you can change the value that the first one returns.Victualage
@MartinBonner ...but only in the constructor.Dkl
or, as always, through reflection (minor nitpicking)Bellboy

© 2022 - 2024 — McMap. All rights reserved.