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.
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.
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.