I used to setup C# class members as follows:
public class MyClass
{
private string member1;
public string Member1{ get; set; }
}
Using Visual Studio 2017 and .NET Framework 4.6.1, when I refactor my code as suggested by VS2017, the same code works perfectly fine, but appears like this:
public class MyClass
{
private string member1;
public string Member1 { get => member1; set => member1 = value; }
}
I would like to know more of what the changes to the get
and set
properties mean.
The property-initialisation syntax is a part of the C# language so is not dependent on the .NET Framework version. The version of Visual Studio you are using does indeed impact on the C# versions available to you, but note that is possible, for example, to use what is at the time of writing the newest C# version - 7.x - with the not-current Visual Studio 2015.
With that out of the way, let's look at some property declarations.
A traditional, bog-standard field-backed C# property declaration would look like this, albeit ideally with more-descriptive naming:
public class MyClass
{
private string member1;
public string Member1
{
get { return member1; }
set { member1 = value; }
}
}
We have a public getter, which returns our private backing field member1
; and a public setter which sets our private backing field.
The above code is likely what you thought you were using in your former life. Here's the code you provided:
public class MyClass
{
private string member1;
public string Member1 { get; set; }
}
...but no. private string member1;
is not referenced by the Member1
property. Indeed in this example, member1
is not referenced at all and may well be optimized away by the compiler! What you really wrote was:
public class MyClass
{
public string Member1 { get; set; }
}
The above is an auto-implemented property, as introduced in C# 3.0. Note that the get
and set
keywords are not followed by bodies.
In C# 3.0 and later, auto-implemented properties make property-declaration more concise when no additional logic is required in the property accessors... When you declare a property [this way], the compiler creates a private, anonymous backing field that can only be accessed through the property's get and set accessors.
So, just like in our "traditional, bog-standard field-backed property" example we get a field-backed property, except this time we don't define the field in our code and it is anonymous to us. In the compiler we trust!
We're almost done. Let's look at your newer code:
public class MyClass
{
private string member1;
public string Member1 { get => member1; set => member1 = value; }
}
get => member1
- this is a property get accessor with an expression body definition, as introduced in C# 6. It is just syntactic sugar equivalent to get { return member1; }
.
set => member1 = value;
is a property set accessor with an expression body definition. This syntax was introduced for setters in C# 7. It is syntactic sugar for set { member1 = value; }
.
To end this summary, C# 6 also introduced initializers for auto-properties. An initializer directly initializes the backing field. Consider this elegant lightweight code to declare and initialize a simple, (hidden, anonymous) field-backed readable and writable property:
public string Member1 { get; set; } = "I am Member 1!"