Let’s go in flashback and try to understand how properties evolved in .Net.
Properties are wrapper over fields which controls the way our fields should be accessed and modified.
A typical field:
private int i = 0;
By default variable in a class are private which means they cannot be accessed outside the classes and are only accessible via member functions.
Making the variable public will mean anybody who has access to class object can modify the variable, which is not a secure way of dealing with class data.
Solution is properties:
A typical .Net 1.1 property
private int _i = 0;
public int I
{
get { return _i; }
set { _i = value; }
}
or we can use access modifiers with properties like:-
public int I
{
get { return _i; }
protected set { _i = value; }
}
Above code means property is available via class objects but only child classes can set.
Come C# 3.0 And Automatic Properties:
C# 3.0 bring about the concept of automatic properties which removed the reliance on creating a field to be encapsulated by a property
public int I { get; set; }
Here compiler created a backing field automatically which is not accessible to code but used internally.
Here is a screengrab of compiled code via ILDASM
As you can see apart from creating get and set methods in MSIL, compiler has also created a backing field which is being wrapped by the getter and setter methods.
Still the gap was the properties can’t have a default value other than default value of type provided by the framework i.e. if you want to initialize property “I” declared above with value 5, we need to do that in constructor e.g.
public int I { get; set; }
public A()
{
I = 5;
}
C# 6.0 – Automatic Property Initializers:
C# 6.0 removed this reliance of setting default properties in constructor by introducing Property Initializer, which is a concise way of providing default values as
class A
{
//Automatic Initialization of a read-write property
public int I { get; set; } = 5;
//Automatic Initialization of a read-only property
public string FirstName { get; } = "Shakti";
public A()
{
// I =5; //No longer needed now
}
}