Read Only Members In Structs In C# 8.0

Introduction

 
In today’s article we will look at a new feature introduced with C# 8.0. This is the ability to declare members of a struct as read only. This indicates that this member does not modify state and it is more granular than applying the read only modifier to the struct declaration. We will explain the benefit of this in the article. C# 8.0 is supported on .NET Core 3.x and .NET Standard 2.1.

Creating a simple console application to demo

 
We start by creating a simple console application using Visual Studio 2019 community edition. The framework used is .NET Core 3.1.
 
In this application, we will create a mutable struct that has two properties. These are the height and width and it calculates the area in another property. Finally, there is a “To String” method which returns a string with the three properties in a string expression. Below is the code:
  1. using System;  
  2.   
  3. namespace CSharp8Features  
  4. {  
  5.     class Program  
  6.     {  
  7.         static void Main(string[] args)  
  8.         {  
  9.             var sq = new Square();  
  10. sq.Height = 20.0;  
  11. sq.Width = 25.0;  
  12. Console.WriteLine(sq.ToString());  
  13. Console.ReadKey();  
  14.         }  
  15.     }  
  16.   
  17.     public struct Square  
  18.     {  
  19.         public double Height { getset; }  
  20.         public double Width { getset; }  
  21.         public double Area => (Height * Width);  
  22.         public override string ToString() =>  
  23.             $"(Total area for height: {Height}, width: {Width}) is {Area}";  
  24.     }  
  25. }  
Like in most structs, the “To String” does not modify state and hence we can add the “readonly” modifier to it as below:
  1. public struct Square  
  2.     {  
  3.         public double Height { getset; }  
  4.         public double Width { getset; }  
  5.         public double Area => (Height * Width);  
  6.         public readonly override string ToString() =>  
  7.             $"(Total area for height: {Height}, width: {Width}) is {Area}";  
  8.     }  
However, when we now build the solution, we get the below warning,
 
Read only members in Structs in C# 8.0
 
The reason for this is that we are calling a non-readonly member (Area) from a readonly member (ToString) which will result in a defensive copy being created. To avoid this, we know that the Area property does not change state and hence we can mark it as readonlyalso, as below:
  1. public struct Square  
  2. {  
  3.     public double Height { getset; }  
  4.     public double Width { getset; }  
  5.     public readonly double Area => (Height * Width);  
  6.     public readonly override string ToString() =>  
  7.         $"(Total area for height: {Height}, width: {Width}) is {Area}";  
  8. }  
Now when we compile the code, we do not get any warning and we see the below,
 
Read only members in Structs in C# 8.0
 
You must note that the readonly modifier is required on a read-only property. The compiler will not assume that get accessors do not modify state. Hence, you must declare readonly explicitly on the property. However, Auto-implemented properties are an exception. The compiler will treat all auto-implemented property getters as readonly. Hence, there is no need to add the readonly modifier to the Height and Width properties.
 

Summary

 
In this article, we looked at how to use the read only modifier with members inside a struct and the benefits of doing this in C#. This is another one of the new features that has been introduced in C# 8.0. I will be covering more of these features in future articles. Happy Coding!