Record types in C#.NET

What are Record Types in C#?

Records in C# 9 provide a way to create immutable value types. The record keyword defines a record type like enums, structs, and classes. However, these other types of constructs, record types are designed to be immutable by default. When you define a record type with properties and methods, the compiler will ensure those properties can never change after they are created.

Anatomy of Record Types in C#

In C# 9, records are a new type that can replace classes and structs. Record structs are introduced in C# 10, allowing you to define records as value types. The difference between records and classes is that records utilize value-based equality. Records of the same type with similar specifications and similar values in all fields are equal.

In C# 9, a record type is a lightweight, immutable data type (or lightweight class) with primarily read-only properties. A record type is thread-safe, and because it is immutable, you cannot change it after it is created. Note that record types can only be initialized inside constructors.

Instead of using the class or struct keywords, you can specify a record type using the record keyword. If you want to indicate that a record is a reference type, you can specify it as a record class. In contrast to a reference type, records have value-based semantics. To create value-type records, you define a record struct. For your record type, the compiler produces a variety of methods to enforce value semantics.

These include overridable versions of Object.Equals,  Object.GetHashCode, and a virtual Equals method that accepts a record type as an argument. It also includes methods for the operators == and !=.

Programming Record types in C#


Refer to the following source code that shows how you can define a record type in C#:

public record Employee
{
   public int Id { get; set; }
   public string FirstName { get; set; }
   public string MiddleName { get; set; }
   public string LastName { get; set; }
   public string Department { get; set; }
   public string Address { get; set; }
   public string Phone { get; set; }
}

Note that the record type we’ve defined is not immutable yet. Since it is not immutable yet, the following source code is perfectly valid:

Employee employee = new Employee();
employee.FirstName = “Ramana”;
employee.MiddleName = “Reddy”;
employee.LastName = "Bhumpalli";
employee.Department = “Development”;
employee.Address = "Hyderabad, Telengana, INDIA";
employee.Phone = "1234567890";

To make the record type immutable, you must use init properties in your record as shown in the source code below:

public record Employee
{
   public int Id { get; init; }
   public string FirstName { get; init; }
   public string MiddleName { get; init; }
   public string LastName { get; init; }
   public string Department { get; init; }
   public string Address { get; init; }
   public string Phone { get; init; }
}

Now if you create an instance of the record and attempt to initialize its members, a compilation error will be generated since your properties are init-only. Note that you can initialize init-only properties inside a constructor only. You can use the following source code to instantiate the record type and initialize its properties:

Employee employee = new Employee()
{
    Id = 1,
    FirstName = “Ramana”,
    MiddleName = “”,
    LastName = "Bhumpalli",
    Department = “Development”,
    Address = “Hyderabad, Telengana, INDIA”,
    Phone = “1234567890”
};

Note that, when you create an instance of a record type in C# using positional parameters, the instance becomes immutable by default. Refer to the following source code that shows how you can create an instance of a record type using positional arguments:

var employee = new Employee(1, "Ramana", “”, "Bhumpalli", “Development”, "Hyderabad, Telengana, India", "0123456789");

The complete source code has been provided below for your reference:

namespace MyRecordDemo
{
    public record Employee
    {
        public int Id { get; init; }
        public string FirstName { get; init; }
        public string MiddleName { get; init; }
        public string LastName { get; init; }
        public string Department { get; init; }
        public string Address { get; init; }
        public string Phone { get; init; }
    }
    internal class Program
    {
        static void Main(string[] args)
        {
            Employee employee = new Employee()
            {
                Id = 1,
                FirstName = "Ramana",
                MiddleName = "",
                LastName = "Bhumpalli",
                Department = "Development",
                Address = "SanathNagar,Hyderabad,
                Phone = "1234567890"
            };
            Console.WriteLine("Employee Id: {0}",employee.Id);
            Console.WriteLine("First Name: {0}", employee.FirstName);
            Console.WriteLine("Middle Name: {0}",
            employee.MiddleName);
            Console.WriteLine("Last Name: {0}", employee.LastName);
            Console.WriteLine("Department: {0}", employee.Department);
            Console.WriteLine("Address: {0}", employee.Address);
            Console.WriteLine("Phone: {0}", employee.Phone);
            Console.Read();
        }
    }
}

Inheritance in Record Types in C#

Inheritance is a powerful concept in object-oriented programming, allowing you to create reusable pieces of code by deriving from a common base class. Record types can be extended to extend other record types, which is one of their most intriguing features. Therefore, you can create a custom record type inherited from another type (another record type or an interface).

public record FullTimeEmployee : Employee

{
   public int Id { get; init; }
   public int NoOfDaysWorked { get; init; }
   public double GrossSalary { get; init; }
   public double Tax { get; init; }
   public double NetSalary { get; init; }
}

Final Thoughts on C# Record Types

Record types are a great new addition to C#. They make it easier to create immutable value types so that you can pass them around without worrying about immutability. They also help reduce the amount of boilerplate code needed when working with objects that have only a few properties and methods, and at the same time, you want those objects to be immutable

Comments

Popular posts from this blog

Email Sending through O365 using OAuth Protocol

IISRESET vs App Pool Recycling ?

Deploy .Net6.0 Web api with docker