C# – How to deconstruct an object

Deconstructing an object means assigning its properties to several variables with a one-liner using deconstruction assignment syntax (also referred to as destructuring or unpacking). To be able to deconstruct an object, it needs to have a Deconstruct() method. Some built-in types have this – tuples, dictionary key/value pairs, records – and you can add it to other types.

Here’s an example of deconstructing a class object:

var coder = new Coder() { Name = "Bob", Language = "C#", YearsExperience = 5 }; var (name, lang) = coder; Console.WriteLine($"{name} is a {lang} coder");
Code language: C# (cs)

This outputs:

Bob is a C# coder
Code language: plaintext (plaintext)

The Coder class has the required Deconstruct() method (void + out parameters):

public class Coder { public string Name { get; set; } public string Language { get; set; } public int YearsExperience { get; set; } public void Deconstruct(out string name, out string language) { name = Name; language = Language; } }
Code language: C# (cs)

Notice that you don’t need to output every property. Just the ones you pick.

When you use the deconstruction assignment syntax on an object, it really just calls its Deconstruct() method. This is syntax sugar and it’s purely based on convention.

In this article, I’ll show a few more deconstruction examples.

Note: A type can have multiple overloaded Deconstruct() methods. This allows you to the use the right one. If you have to use a deconstructor with unwanted properties, discard them with _.

Deconstruct a tuple

Deconstructing tuples is the most common scenario for deconstruction. Here’s one of example of using tuple deconstruction.

Splitting a string gives you an array of strings, which you can access by index. This can be error prone and it’s not very helpful to use “arr[1]” all the over the place. One idea is to put the split values into a tuple and then deconstruct the tuple into named variables. Here’s an example:

var fields = "Bob,C#,5".Split(","); var (name, lang, years) = (fields[0], fields[1], fields[2]); Console.WriteLine($"{name} has used {lang} for {years} years");
Code language: C# (cs)

This outputs the following:

Bob has used C# for 5 years
Code language: plaintext (plaintext)

You might be thinking, couldn’t you just put three lines of code to assign to these variables? Yes, you could, but remember that deconstruction is syntax sugar and it’s all about reducing this down to a single line.

Deconstruct a dictionary’s key/value pairs

The dictionary key/value pair type implements Deconstruct(), so these can be deconstructed into well-named key and value variables. Here’s an example:

var wordCountMap = new Dictionary<string, int>() { ["apple"] = 10, ["dog"] = 5, ["fish"] = 6 }; foreach(var (word, count) in wordCountMap) { Console.WriteLine($"{word} appeared {count} times"); }
Code language: C# (cs)

This outputs the following:

apple appeared 10 times dog appeared 5 times fish appeared 6 times
Code language: plaintext (plaintext)

This is a nicer than using a KeyValuePair loop variable (ex: kvp.Key and kvp.Value).

Add Deconstruct() as an extension method

When you want to be able to use deconstruction on a type that doesn’t have Deconstruct() implemented, and you can’t directly change the type (third-party or built-in), you can add Deconstruct() as an extension method for the type.

For example, let’s say you’re using the following Coder class from a third-party library:

public class Coder { public string Name { get; set; } public string Language { get; set; } public int YearsExperience { get; set; } }
Code language: C# (cs)

You attempt to deconstruct a Coder object, but you get hit with a bunch of compiler errors because it doesn’t have a Deconstruct() method:

//CS1061 - 'Coder' does not contain a definition for 'Deconstruct'... (and 3 other errors) var (name, lang) = coder;
Code language: C# (cs)

You can’t directly modify the Coder class (third-party), but you can implement Deconstruct() as an extension method:

public static class CoderExtensions { public static void Deconstruct(this Coder coder, out string name, out string language) { name = coder.Name; language = coder.Language; } }
Code language: C# (cs)

Now you can deconstruct the Coder object.

A type can have multiple Deconstruct() implementations. So even if a class has a Deconstruct() method already, you can add your own extension method to get exactly the properties you want.

Leave a Comment