Using Deconstructors in C# 7.0

This is another awesome feature that got introduced with C# 7.0 which can be helpful in many scenarios while consuming various objects. Deconstruction is mostly discussed with another new feature System.ValueTuple but it can be used with other custom type as well. I have also discussed it in briefly in ValueTuple post at the link below. I will advise to go through that first before starting here.

How to use the new ValueTuples : A C# 7.0 feature

What is Deconstruction

It is a process of splitting an instance’s (value types and reference types) value into multiple parts and assigning them to new variables. Like, I mentioned that it is extremely useful with the Tuples which contains a set of values but can be used with other types.

How to use Deconstruction

We can leverage it in our custom classes, structs or interfaces. We need to implement Deconstruct method, which returns void and each deconstructed value should be added as out parameter in the method signature. We can have multiple overridden Deconstruct method based on the requirement. Let’s see an example

public class Person
{
    public string FirstName { get; set; }

    public string MiddleName { get; set; }

    public string LastName { get; set; }

    public int Age { get; set; }

    public Person(string fName, string mName, string lName, int age)
    {
        FirstName = fName;
        MiddleName = mName;
        LastName = lName;
        Age = age;
    }
    public void Deconstruct(out string fName, out string lName)
    {
        fName = FirstName;
        lName = LastName;
    }

    public void Deconstruct(out string fName, out string lName, out int age)
    {
        fName = FirstName;
        lName = LastName;
        age = Age;
    }
}

Here we can see that I have provided two Deconstruct methods, one with two out parameters: fName, lName and other with three : fName, lName, age.

Person p = new Person("Brij", "Bhushan", "Mishra", 32);

//(string firstName, string lastName) = p;
// OR
var (firstName, lastName) = p;

Console.WriteLine($"Person Details: First Name: {firstName}, Last Name: {lastName}");


(string firstName, string lastName, int age) = p;

Console.WriteLine($"Person Details: First Name: {firstName}, Last Name: {lastName}, Age: {age}");

Here I created the instance of Person with all the details. Then in first deconstruction, we got the first name and last name which calls the first Deconstruct method of the class which has two out parameters. Note that we have two ways of deconstruction. First we explicitly declare the type of each field inside parentheses (commented out) and another, using var keyword so that C# infers the type of each variable. Similarly later, second Deconstruct method is called which deconstructs it in three variables. It can be really useful when we have a class with numerous properties, fields and most of the time, we need only few there we can use the Deconstruct methods.

Similar to ValueTuples, we can use discards here as well. To discard a variable of Deconstruct method, we can use underscore (_) as

Person p = new Person("Brij", "Bhushan", "Mishra", 32);
(string firstName, _ , int age) = p;

Console.WriteLine($"Hello {firstName}, your age is {age}");

Deconstruction use Extension method

There could be scenarios where you want to this feature but its an existing class where changes are not possible (like some third party classes, classes own by different team or even framework classes), there we can add this as an extension method. Lets assume that Person class doesn’t have Deconstruct methods and we can add it as an extension method as

public static class DeconstructionExtensions
{
    public static void Deconstruct( this Person p, out string fName, out string lName, out int age)
    {
        fName = p.FirstName;
        lName = p.LastName;
        age = p.Age;
    }
}

It will work in the same way as earlier.

Hope you have enjoyed the post and will be able to use in your day to day coding.

Thanks
Brij

Advertisement

C# 6.0 and 7.x posts links

Hello All,

There are rapid changes to C# language recently. Although these are very useful in writing cleaner, concise, less repetitive and performance oriented code, I see very less usage of these in our day to day coding. So I thought of writing these features as blog posts to learn myself and share with others. In this post I am just listing down the links of my earlier C#6.0 and C# 7.x blog posts so that it is easily available. Do let me know if there is any important feature that I missed which could be useful in our day to day coding.

C# 6.0 features

C# 7.X features

Hope you’ll enjoy these posts and able to use these in your day to day development.

Cheers,
Brij

How to use the new ValueTuples : A C# 7.0 feature

Tuples are one of the awesome features of C# which was initially introduced with .NET 4.0. Although it is less used but it become very handy when we need to return multiple values from a function. We have another option to use out operator but it is not recommended due to various reasons. I am not going to discuss it in this post. Tuple is a static class under namespace System which implements a Factory pattern to create the instances of Tuples. It has a Create method with eight overloads which allows us to have 8 elements in a Tuple. Also, we can have nested tuples as well.

There were few issues with System.Tuple. It is a reference type so even if you are returning few values type elements , the instance gets created on heap, means adding pressure on Garbage Collector. It doesn’t allow to provide a name to the elements, instead we have to refer it as item1, item2.. etc. Also, the way we used to create Tuple is also quite verbose.

Tuple in C# 7.0

C# 7.0 introduces System.ValueTuple as a new language feature, which resolves the problems mentioned above and provides few more additional features. And Yes, it has the power of Value Type so it removes the GC overhead of the old tuple.

Note: ValueTuple is available as indepedent nuget package. You can install it from here.

Lets see few examples of new Value Tuples,

Tuple Literals

Tuple literal is a comma separated list of literal (of various types), surrounded by parenthesis.

static void Main(string[] args)
{
    // Tuple Literals
    var tpl = (1, 2);
    var author = ("Brij", 32, "https://codewala.net/");
}

public (string, int, string) Author { get; set; } = ("Brij", 32, "https://codewala.net/");

Here we can see that creating Tuple is now a simple assignment operation. Also we can have different types in a Tuple which helps in combining various set of information in a tuple based on the need.

Using Tuples as Return Type

We can use value tuple as return type and the syntax looks so simple as


var author = GetAuthor();

Console.WriteLine($"Author Details: Name: {author.Item1}, Age: {author.Item2}, BlogURL : {author.Item3 ?? "URL not available" } ");

private static (string, int, string) GetAuthor()
{
    string name = "Amit Kumar";
    int age = 33;
    return (name, age, null);
}

Naming the Tuple Elements:
Yes, we can name the tuple elements and this also provides the intellisense support. This is one of the best improvements. We can write the above code as

var author = GetAuthor();
WriteLine($"Author Details: Name: {author.name}, Age: {author.age}, BlogURL : {author.url ?? "URL not available" } ");

private static (string name, int age, string url) GetAuthor()
{
    string name = "Amit Kumar";
    int age = 33;
    return (name, age, null);
}

We can give names in tuple literal as well

var author = (name: "Brij", age: 32, url: "https://codewala.net/");      
Console.WriteLine($"Author Details: Name: {author.name}, Age: {author.age}, BlogURL : {author.url ?? "URL not available" } ");
// Or we can also write as
(string name, int age, string url) author = ("Brij", 32, "https://codewala.net/");

Let’s move to another exciting feature

Value Tuple Deconstruction

Value tuple allows us deconstruct the tuple and access the elements as a local variable. We need to assign a tuple to variable surrounded by parenthesis.  Broadly, it can be done in three ways

  • Providing the types of each element in parenthesis.
  • Using var keyword outside the parenthesis (it is applied to each variable).
  • Or using existing variables

Lets see the examples


// First Option - Providing the type of each element. var is also allowed.
(string authorname, int age, var blog) = GetAuthor();
Console.WriteLine($"Author Details: Name: {authorname}, Age: {age}, BlogURL : {blog ?? "URL not available" } ");

// Second Option - Using var outside of the parenthesis
var (authorname, age, blog) = GetAuthor();
Console.WriteLine($"Author Details: Name: {authorname}, Age: {age}, BlogURL : {blog ?? "URL not available" } ");

// Third option - Using existing variables
string authorname = "Brij";
int age = 32;
string blog = "https://codewala.net/";

(authorname, age, blog) = GetAuthor();
Console.WriteLine($"Author Details: Name: {authorname}, Age: {age}, BlogURL : {blog ?? "URL not available" } ");			

Now it may happen that you are not sure about all the elements or want to discard few , you can use underscore (_) as

var (authorname, age, _) = GetAuthor();
Console.WriteLine($"Author Details: Name: {authorname}, Age: {age}");

Last thing, as we have now System.Tuple and System.ValueTuple both, ValueTuple provide a nice extension method as ToTuple() to convert it to System.Tuple.

C# 7.1 Enhancements: 

There are a small enhancement in C# 7.1 which can save few keystrokes as now elements names are inferred from the variables. Let’s see the example

// Earlier
string name = "Brij";
int age = 32;
string blog = "https://codewala.net/";
var author = (name: name, age: age, blog: blog);

// With C# 7.1 
string name = "Brij";
int age = 32;
string blog = "https://codewala.net/";
var author = (name, age, blog); // Element names would be - name, age, blog

Hope you have enjoyed this post and will be able to use in your day to day coding.

Cheers,
Brij

Use the awesomeness of Pattern Matching with C# 7.0

Pattern Matching is a new feature which was introduced with C# 7.0 which allows us to write cleaner and concise code in many different scenarios. This feature can be said as an extension of is and as operators that we already have in C#. I wrote a post on it earlier, you can take a look here. This feature can be broadly devivded in two sections

  1. Using Is Expression
  2. Using Pattern Matching in Switch Statements

Using Is Expression:

Prior to C# 7.0, Is operator was used to check the type of a variable and based on the type, it returns true or false but with C# 7.0, Is Expression provides following three types of pattern matching

  1. Const Pattern
  2. Type Pattern
  3. Var Pattern

Let’s discuss each with examples

Const Pattern: It allows us to check an object with any value. Let’s see an example

static void IsConstExpression()
{
    Object obj = 2;
    string name = "Brij";

    // null check
    if (obj is null)
        Console.WriteLine("Obj is null");

    // Constant value check
    if(obj is 2)
        Console.WriteLine("Obj has value 2");

    // String value check
    if(name is "Brij")
        Console.WriteLine("name has value \"Brij\"");
}

Above, we can see that we can check to any value including null.

Type Pattern: It allows us to confirm the type of the object and also assigns the value to a new variable of the given type. Prior to C# 7.0, we also had the similar feature but here we can assign to the new variable as mentioned. Lets see the example

static void IsTypeExpression()
{
    Object obj = 2;

    var objPerson = new Person() { FirstName = "Brij", LastName="Mishra" };
    var objNewPerson = new Employee() { FirstName = "Anvit", LastName = "Mishra", Company ="ABC Ltd" };

    if (obj is int i)
        Console.WriteLine($" Variable i has the value {i}");

    if (objPerson is Person person)
        Console.WriteLine($" p is of type {person.GetType().Name} and first name is {person.FirstName}");

    if (objNewPerson is Employee newPerson)
        Console.WriteLine($" p is of type {newPerson.GetType().Name} and first name is {newPerson.Company}");

    if (objNewPerson is Person objPer)
        Console.WriteLine($" p is of type {objPer.GetType().Name} and first name is {objPer.FirstName}");

}

Lets see the output

 

Here Employee inherits from Person. So in the last statement, we have the actual object of Employee but it assigned to a variable of base type.

Var Pattern: This is special case pattern where we check the type as var. This has one difference with the type pattern as it returns true even if it is null. Let’s see example

static void IsVarExpression()
{
    Object obj = new Person() { FirstName = "Brij", LastName = "Mishra" };

    if (obj is var p)
    {
        Console.WriteLine($"Var Pattern : P is of type {p?.GetType().Name}.");
    }

    obj = null;

    if (obj is var per)
    {
        Console.WriteLine($"Var Pattern : P is of type {per?.GetType().Name}.");
    }
}

The output will be as

Here we can see that the second check is also true but since it is null, nothing it displayed where we wrote the type name. Now lets move to switch statements.

Pattern Matching in Switch Statements:

The patterns that we discussed in previous section, can be leveraged in switch statements as well. This becomes very handy when the number of testing conditions grows and using Is pattern becomes tough to maintain.

Earlier switch statement was only supporting constant pattern with limited value types and strings but now we can use Type and var patterns as well. Let’s see the example

switch(p)
{
    case Manager objM:
        Console.WriteLine("p is of Manager type");
        break;
    case Employee objE:
        Console.WriteLine("p is of Employee type");
        break;
    case Person objP:
        Console.WriteLine("p is of Person type");
        break;
    case null:
        Console.WriteLine("p is null");
        break;
}

Here Person is the base class and with the hierarchy Person->Employee->Manager. Based on the type of p case statement gets executed and in case of null, last one gets executed. Here, the key is the most derived type should be first statement. Compiler also gives a warning if the order is not correct. C# 6.0 also provides us capability to use When clause in switch case. Let’s see the example

switch(p)
{
    case Employee objE when objE.Grade == 5:
        Console.WriteLine($"{objE.FirstName} is Manager");
        break;
    case Employee objE when objE.Grade == 5 && objE.Rating >= 3:
        Console.WriteLine($"{objE.FirstName} is Manager and eligible for additional bonus");
        break;
    case var objVar:
        Console.WriteLine("P is not a Employee and is of Type {objVar?.GetType().Name}   ");
        break;
}

Here we can see we can add additional filters in case statements which can be very useful in many scenarios. It also allows to add more that one filter and have various kind of combinations. I have used the var pattern as well in last case statement.

Hope you have enjoyed the post and will be able to use this feature in your day to day work.

Cheers,
Brij