Some cool things you can do with ValueTuple

5/18/2023
3 minute read

In this blog post, we will explore some cool things you can do with ValueTuple. Also, a short explanation of what ValueTuple is and how it works.

What is ValueTuple?

ValueTuple in C# is a lightweight, mutable value type that enables grouping multiple values or related data together for various purposes, such as returning multiple values from a method, creating structured data, or combining values in dictionaries. It provides better performance compared to traditional reference types, as it doesn't require heap allocation.

(string FirstName, string LastName, int Age) person = ("Steven", "Giesel", 31);
person.FirstName;  // returns "Steven"
person.LastName; // returns "Giesel"
person.Age; // returns 31

static (string FirstName, string LastName, int Age) GetPerson() 
{
    return ("Steven", "Giesel", 31);
}

Okay, that should be good enough. Let's start with some stuff we can do with that.

Swap two values

Let's say we have two variables and want to swap their values. We can do that with ValueTuple in a single line of code.

int a = 1;
int b = 2;

// Here the swap
(a, b) = (b, a);

Easy IEquatable implementation

ValueTuple can be leveraged to have an easy and readable implementation of IEquatable

public class Dimension : IEquatable<Dimension>
{
    public Dimension(int width, int height)
        => (Width, Height) = (width, height);

    public int Width { get; }
    public int Height { get; }

    public bool Equals(Dimension other)
        => (Width, Height) == (other?.Width, other?.Height);

    public override bool Equals(object obj)
        => obj is Dimension dimension && Equals(dimension);

    public override int GetHashCode() 
        => (Width, Height).GetHashCode();
}

This also shows an easy way to compare two objects as well as receiving the hash code of the object.

Pattern matching with ValueTuple

ValueTuples can be used in conjunction with pattern matching, enabling elegant and expressive code when working with different cases.

(string Name, int Age) person = ("Alice", 25);

string description = person switch
{
    ("Alice", >= 0 and < 13) => "Alice is a child.",
    ("Alice", >= 13 and < 20) => "Alice is a teenager.",
    ("Alice", >= 20 and < 65) => "Alice is an adult.",
    ("Alice", _) => "Alice is a senior.",
    (_, >= 0 and < 13) => "The person is a child.",
    (_, >= 13 and < 20) => "The person is a teenager.",
    (_, >= 20 and < 65) => "The person is an adult.",
    _ => "The person is a senior."
};

Deconstruction of custom types

ValueTuples can be used to enable deconstruction of custom types, allowing your type to be broken down into separate variables easily.

public class Student
{
    public string Name { get; set; }
    public int Age { get; set; }

    public void Deconstruct(out string name, out int age)
    {
        name = Name;
        age = Age;
    }
}

var student = new Student { Name = "John", Age = 21 };

// Deconstruct the Student object into separate variables
(string studentName, int studentAge) = student;

Conclusion

There you got it - some ways where ValueTuple can be used to make your code more readable and easier to understand.

Having fun with ValueTuple

Just as a heads up: This blog post will probably bring you 0 value in your daily life - well, maybe a short smile. Let's put ValueTuple to its extreme!

How to enumerate through a StringBuilder

Did you ever wonder how we can iterate through a StringBuilder? I mean, of course, we can just call ToString and use the returned string, but that means we materialize the whole thing without good reason.

We can also use a normal for-loop. But we can also find a completely different and probably dumber way! And if you wonder: No, this is not something you do in your daily life, but by doing so, I can show some cool stuff C# and .NET offer.

Central nuget store for your UNO Platform App

With the newest UNO Platform update to .NET 6 we can leverage some cool things to simplify our dependency management. We combine .NET 6 with the new feature called Directory.Build.props to make that work.

An error has occurred. This application may no longer respond until reloaded. Reload x