C#

Everything about Tuples in C# and When to Use?

In this post on Everything about Tuples in C# and When to Use? I will explain the tuples in C# in detail with the help of several examples. The most important point about tuples is that they allow you to group multiple unrelated data values in the same data structure and therefore the tuples provide the benefit of flexibility and ease of working with methods and returning values.

Basically, tuples became a part of C# since the introduction of C# 7.0, and many times we use them in place of classes. Sometimes we need to return multiple values from a function. In that situation, we can use tuples if we don’t wish to use out parameters. Also, when we don’t want to create a separate type to hold the properties of an object, we can simply use tuples.

What is a Tuple?

C# offers a number of data structures in the namespace called Collections that contain multiple values. For instance, we have arrays, lists, stacks, queues, dictionary and so on. However, the values that these collections contain are related in some way. On the other hand, a tuple is a data structure that accommodates multiple values. However, not all values that a tuple contains should be of the same data type. In other words, if we wish to create a data structure comprising values with mixed data types, we can use tuples.

System.ValueTuple vs System.Tuple

Additionally, we can have both value type tuples as well as reference type tuples. Basically, System.ValueTuple is a value type rather than a class or a reference type. However, the System.Tuple is a class. In fact, the System.Tuple offers several properties that can be accessed by using its objects.

Value Tuples

In C#, System.ValueTuple struct represents a value tuple. In fact, value tuples became the part of .NET Framework later than the reference tuples. The value tuples are introduced in .NET Framework 4.7. In contrast to reference tuples, value tuples are structures. Therefore, the data members of value tuples like Item1, Item2, Item3, and so on are fields rather than properties. The following example specifies how to create value tuples.

using System;
namespace ValueTupleDemo1
{
    class Program
    {
        static void Main(string[] args)
        {
            ValueTuple<int, int, string, double> t1 = (1, 2, "abc", 6.78);
            Console.WriteLine(t1.Item4);

            ValueTuple t2;
            Console.WriteLine(t2);

            ValueTuple<int, int, int, int, int, int, int> t3 = (1, 2, 3, 4, 5, 6, 7);

            //Creating a value tuple using Create() method
            (int a, int b, int c) t4 = ValueTuple.Create(10, 20, 30);
            Console.WriteLine($"a = {t4.a}, b = {t4.b}, c = {t4.c}");

            //Creating a Nested Value Tuple
            var t5 = ValueTuple.Create(11, 22, 33, ValueTuple.Create("a", "b", 1.5));
            Console.WriteLine("{0}, {1}, {2}, {3}, {4}, {5}", t5.Item1, t5.Item2, t5.Item3, t5.Item4.Item1, t5.Item4.Item2, t5.Item4.Item3);

            //Creating another nested value tuple
            var t6 = (100, 200, (2.1, 3.4, "xyz"));
            Console.WriteLine("{0}, {1}, {2}, {3}, {4}", t6.Item1, t6.Item2, t6.Item3.Item1, t6.Item3.Item2, t6.Item3.Item3);
        }
    }
}

Output

Creating Value Tuples
Creating Value Tuples

To further emphasize the concept of value tuples, let us create some of them as shown in following example. As evident from the code given below, we can create tuples by mixing data types and access the individual fields using the Item property of the tuple.

Example of Value Type Tuples

using System;
namespace ValueTupleDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Tuple 1: ");
            //Example 1
            (int, int) t1 = (8, 12);
            Console.WriteLine("Tuple: {0}, {1}", t1.Item1, t1.Item2);

            Console.WriteLine("Tuple 2: ");
            //Example 2
            (int x, double y) t2 = (12, 12.5);
            Console.WriteLine("Tuple: {0}, {1}",t2.x, t2.y);

            Console.WriteLine("Tuple 3: ");
            //Example 3
            (string s, int i, int j) t3 = ("Hello World", 10, 20);
            Console.WriteLine("Tuple: {0}, {1}, {2}, {3}", t3.s, t3.i, t3.j, t3.i+t3.j);

            Console.WriteLine("Tuple 4: ");
            var t4 = (1, 2, 3, 4, 5, 6);
            Console.WriteLine($"{t4.Item1}, {t4.Item2}, {t4.Item3}, {t4.Item4}, {t4.Item5}, {t4.Item6}");
        }
    }
}

Output

Value Type Tuples
Value Type Tuples

Reference Tuples

The .NET Framework 4.0 introduced a Tuple<T> class which represents the reference tuples. In contrast to the value tuples, reference tuples are the objects of the Tuple<T> class. In fact, the reference tuples also hold multiple unrelated values. However, these tuples can store maximum eight values. The following examples shows how to create a reference tuple using the Tuple class.

Example of System.Tuple

using System;
namespace ReferenceTuplesDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            var t = Tuple.Create(1, 2, 3, 4, 5, 6, 7, 8);
            Console.WriteLine("{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}", t.Item1, t.Item2, t.Item3, t.Item4, t.Item5, t.Item6, t.Item7, t.Rest.Item1);
        }
    }
}

Output

Creating a Reference Tuple
Creating a Reference Tuple

When Should We Use Tuples?

There are a number of reasons when we prefer to use tuples instead of using any other construct. Firstly, suppose we need to return multiple values from a method, then instead of using out parameters, we can return a tuple. Secondly, suppose we need to create an object of a class just to hold the result of a LINQ query. In that case, we can use a tuple rather than creating a separate class. Thirdly, we can store the key/value pair of an instance of a Dictionary in a tuple. The examples of all these scenarios are given next.

Example 1

The following example shows how to use a tuple for returning two different values from a function without using the out parameter. As evident, the function f1 returns the value of sum and difference as a tuple. In this example, a value tuple is storing both of the resulting values.

using System;
namespace TuplesDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            int a, b;
            (a, b) = f1(10, 20);
            Console.WriteLine("Sum = {0}, Difference = {1}", a, b);
        }
        static (int, int) f1(int x, int y)
        {
            int m, n;
            m = x + y;
            n = x - y;
            (int m, int n) ob=(m, n);
            return ob;
        }
    }
}

Output

A Simple Example of Tuple
A Simple Example of Tuple

Example 2

We can also use tuples along with dictionaries to hold Key/Value pairs. In fact, we can search for a key and if it is found, return the corresponding Key/Value pair as a tuple. The following example shows how a tuple is storing the resulting values of the key/value pair of the dictionary. In this example, he search method takes a key as the parameter, and finds whether it is present in the dictionary or not. In case, the key is found, the corresponding key/value pair is returned as a tuple.

using System;
using System.Collections.Generic;
namespace TuplesDemo2
{
    class Program
    {
        Dictionary<int, string> dct = new Dictionary<int, string>();
        static void Main(string[] args)
        {
            Program ob = new Program();
            ob.dct.Add(1, "Red");
            ob.dct.Add(2, "Orange");
            ob.dct.Add(3, "Pink");
            ob.dct.Add(4, "Blue");
            ob.dct.Add(5, "Green");
            ob.dct.Add(6, "Yellow");
            ob.dct.Add(7, "Black");

            Console.WriteLine("Enter Key to search: ");
            int x = Int32.Parse(Console.ReadLine());

            (int a, String s) = ob.search(x);
            if (!String.IsNullOrEmpty(s))
                Console.WriteLine("Key/Value Pair: ({0},{1})", a, s);
            else
                Console.WriteLine("Key not found!");
        }
        Tuple<int, string> search(int x)
        {
            Tuple<int, string> t1 = new Tuple<int, string>(0, "");
            foreach(int k in dct.Keys)
            {
                if (k == x)
                    t1 = new Tuple<int, string>(k, dct[k]);
            }
            return t1;
        }
    }
}

Output

Using Tuples with Dictionary
Using Tuples with Dictionary

Example 3

Tuples can be used with LINQ (Language Integrated Queries) as well. As evident from the following example, a reference tuple is storing the three values which the query is returning. Also, the use of tuple avoids the need of creating a separate class Temp to just hold the result of query.

using System;
using System.Linq;
namespace LINQDemo1
{
    class Temp
    {
        public int a, b, c;
    }
    class Program
    {
        static void Main(string[] args)
        {
            int[] arr = {1,2,3,4};

            //use of a tuple for holding the multiple values returned by a LINQ query
            var q = from i in arr
                    select new Tuple<int, int, int>(2 * i, i * i, i * i * i);

            foreach(var x in q)
            {
                Console.WriteLine("Twice = {0}, Square = {1}, Cube = {2}", x.Item1, x.Item2, x.Item3);
            }

            // Without tuple we need to declare a class for storing multiple 
            // values returned by a class
            var q1 = from i in arr
                     select new Temp {a=2*i, b=i*i, c=i*i*i };
            foreach (var x in q1)
            {
                Console.WriteLine("a = {0}, b = {1}, c = {2}", x.a, x.b, x.c);
            }


        }

    }
}

Output

Using Tuples in LINQ
Using Tuples in LINQ

Summary

In this article I have described Everything about Tuples in C# and When to Use them and also when we can just use a tuple instead of a class. Further, we can have both value tuples and reference tuples that we can use in many situations. Overall, use of tuples provide a number of benefits in terms of flexibility, efficiency and productivity.


Related Topics

Linear Search and Binary Search in C#

Creating Jagged Arrays in C#

Learning Indexers in C#

Understanding Method Parameter Modifiers in C#

Object Initializers in C#

Examples of Static Constructors in C#

When should We Use Private Constructors?

C# Practice Questions

C# Basic Examples

Private and Static Constructors in C#

Constructors in C#

C# Arrays

C# Examples

How to Create a C# Console Application

Leave a Reply

Your email address will not be published. Required fields are marked *