C# – 9.0

In this post, we will see two interesting features introduced with C# 9.0.
For the complete list of all new features, we can go to Microsoft web site.


[RECORDS]
Records provide an extremely fast way to define an immutable object with value type semantics.

using System;
namespace csharp_9
{
    class Program
    {
        // Definition of a record
        private record user(Guid Id, string UserName, string Password);
        
        static void Main(string[] args)
        {
            var userOne = new user(Guid.NewGuid(), "UserName1", "Password1");
            Console.WriteLine(userOne);
        }
    }
}


If we run the application, this will be the result:


Immutable
If we try to change a value in userOne, we will receive a compile error:


In order to make userOne mutable, we have to define in different way the record User:

using System;
namespace csharp_9
{
    class Program
    {
        // Definition of a record
        private record user(Guid Id, string UserName, string Password)
        {
            public Guid Id { get; set; } = Id;
            public string UserName { get; set; } = UserName;
            public string Password { get; set; } = Password;
        }

        static void Main(string[] args)
        {
            var userOne = new user(Guid.NewGuid(), "UserName1", "Password1");
            Console.WriteLine(userOne);

            userOne.Password = "NewPassword";
            Console.WriteLine(userOne);
        }
    }
}


And now, if we run the application, this will be the result:


Obviously, we can decide which parameter we want to make mutable:

using System;

namespace csharp_9
{
    class Program
    {
        // Definition of a record
        private record user(Guid Id, string UserName, string Password)
        {
            public string Password { get; set; } = Password;
        }

        static void Main(string[] args)
        {
            var userOne = new user(Guid.NewGuid(), "UserName1", "Password1");
            Console.WriteLine(userOne);

            userOne.UserName = "NewUser";
            userOne.Password = "NewPassword";
            Console.WriteLine(userOne);
        }
    }
}


In this case, we will have a compile error, because UserName is immutable.


With expression
The “with expression” allow us to create a new Record from another:

using System;
namespace csharp_9
{
    class Program
    {
        // Definition of a record
        private record user(Guid Id, string UserName, string Password);

        public static void Main(string[] args)
        {
            var userOne = new user(Guid.NewGuid(), "UserName1", "Password1");
            Console.WriteLine(userOne);

            var userTwo = userOne with { UserName = "UserName2", Id = Guid.NewGuid() };

            Console.WriteLine(userTwo);
        }
    }
}


if we run the application, this will be the result:



[INIT ONLY SETTERS]
With “Init Only Setters” we can decide to initialise a property only in the constructor:

using System;

namespace csharp_9
{
    class Program
    {
        public static void Main(string[] args)
        {
            var userAdmin = new Admin(Guid.NewGuid(), "UserAdmin1", "Password123");
            Console.WriteLine($"{userAdmin.Id} - {userAdmin.UserName} - {userAdmin.Password}");

            userAdmin.Password = "Password456";
            Console.WriteLine($"{userAdmin.Id} - {userAdmin.UserName} - {userAdmin.Password}");
        }
    }

    class Admin
    {
        public Guid Id { get; init; }
        public string UserName { get; init; }
        public string Password { get; set; }

        public Admin(Guid id, string userName, string password)
        {
            Id = id;
            UserName = userName;
            Password = password;
        }
    }
}


If we run the application, this will be the result:


But, if we try to change a property defined as “init”, we will have a compile error: