Author avatar

Dániel Szabó

Declare and Initialize Read-only Auto Properties in C#

Dániel Szabó

  • Mar 20, 2020
  • 5 Min read
  • 548 Views
  • Mar 20, 2020
  • 5 Min read
  • 548 Views
Languages
Frameworks
and Tools
Programming Languages
Hosted
C#

Introduction

Version 6 of C#, released in 2015 alongside Visual Studio ultimate, implemented a unique feature: The read-only auto-property, sometimes referred to as the getter-only auto-property. In this guide, we will take the concepts of fields and properties and see how both can be read-only and how they are implemented while focusing on the auto-property aspect. We will also see how this new feature gave developers more ways to overcome problems and challenges.

Fields vs. Properties

These two concepts revolve around the idea of abstraction. With a class, you can have fields and properties. Fields are normal variable members. Properties are abstractions that allow you to get or even set their values.

Let's look at an example of fields. We have a server ServerFieldDemo class with two members.

1
2
3
4
5
6
7
8
9
10
public class ServerFieldDemo
{
    private string _Name;
    private string _Function;
    
    public ServerFieldDemo(string name, string function){
        this._Function = function;
        this._Name = name;
    }
}
csharp

When you define fields, you should make sure you define them as private as this ensures you are not violating the concept of encapsulation. Encapsulation, in short, means that you are bundling the fields or data with methods and functions that are capable of manipulating them without exposing them for direct manipulation. This current code is not sufficient as it is not able to retrieve these members.

In order to imbue our class with properties, also called accessors, modify the class in the following way.

1
2
3
4
5
6
7
8
9
10
11
12
public class ServerFieldDemo
{
    private string _Name;
    private string _Function;
    public string Name { get { return _Name; } set {_Name = value; } }
    public string Function { get { return _Function; } set { _Function = value; } }

    public ServerFieldDemo(string name, string function){
        this._Function = function;
        this._Name = name;
    }
}
csharp

You now have the option to read and modify the properties. Call the code.

1
2
3
4
5
ServerFieldDemo a = new ServerFieldDemo("pikkolo", "Domain Controller");
Console.WriteLine($"The name is: {a.Name} and function is: {a.Function}");
a.Name = "songoku";
a.Function = "DNS Server";
Console.WriteLine($"The name is: {a.Name} and function is: {a.Function}");
csharp

You should see the following output upon execution.

1
2
he name is: pikkolo and function is: Domain Controller
The name is: songoku and function is: DNS Server
bash

You have initialized the class with the help of the constructor, and the fields were changed with the help of the property accessors. You have obeyed the encapsulation principle, as well. Now that you clarified the concepts, spice it up with the read-only aspect.

To create a read-only field, use the readonly keyword in the definition.

1
2
3
4
5
6
7
8
9
10
public class ServerFieldDemo
{
    readonly string _Name;
    readonly string _Function;
    
    public ServerFieldDemo(string name, string function){
        this._Function = function;
        this._Name = name;
    }
}
csharp

In the case of a field member, you get only one chance to initialize the field with a value, and that is when you call the class constructor. Beyond that, you'll would get an error for such attempt. The problem with the above class is that you cannot access the fields. You need to find a workaround for that. You still want to keep in mind the read-only aspect, so the property can only be retrieved for the class but not modified. With a little modification to the code, you can demonstrate this.

1
2
3
4
5
6
7
8
9
10
11
public class ServerFieldDemo
{
    private string _Name;
    private string _Function;
    public string Name { get { return _Name; } }
    public string Function { get { return _Function; } }
    public ServerFieldDemo(string name, string function){
        _Name = name;
        _Function = function;
    }
}
csharp

Now take the class for a test drive.

1
2
ServerFieldDemo a = new ServerFieldDemo("pikkolo", "Domain Controller");
Console.WriteLine($"The name: {a.Name}, function: {a.Function}");
csharp

The output of the code is as follows.

1
The name: pikkolo, function: Domain Controller
bash

If you attempt to rename the class like this ...

1
a.Name = "New Name";
csharp

... the compiler will show the following error.

1
CS0200	Property or indexer 'ServerFieldDemo.Name' cannot be assigned to -- it is read only	Pluralsight	
bash

The reason for this is that the setter was omitted from the property definition, and now you can only access but not modify the property deeper inside the field of the class.

This change allows you to keep the internal structure of the class intact and prevent any modifications. All in all, if you want to create read only properties, just omit the definition of the setter in that specific property while making sure the field stays private so you do not violate the principle of encapsulation.

Conclusion

In this guide, you learned about fields and propertiesand how they are related to each other, followed by how to protect data and integrity encapsulated in a class with the read-only concept. I hope this has been informative to you and I would like to thank you for reading it!

10