Share via


C# 7 : Tuple

Introduction

Tuple is an ordered sequence of heterogeneous objects. We may often write methods which return multiple values so we need to create a simple structure containing more than one data elements. To support these scenarios, tuples were added to C#. Tuples are lightweight data structures that contain multiple fields to represent the data members.

If a method returns multiple homogenous values, then it stores these values in the collection and returns that collection. But a method needs to return multiple heterogenous values, then C# provides some options such as Class/Struct, out parameter and Tuple.

Let’s create an example. We have a collection of integer numbers and we need to find out the minimum and maximum number from this collection. We need to create a method which returns both Minimum and Maximum values. To achieve this, we have three options which are Class/Struct, out parameter, and Tuple. So, let’s see each option one by one.

Using Out Parameter

As we create a method which finds the maximum and minimum number in the number series. This method has two values as a result of a maximum and minimum number. So, we create the method which returns a value and use out parameter as argument. The return value holds a maximum number from series while out parameter holds a minimum number from series./p>

Let’s create a class named Operation which holds a method to find a minimum and maximum number from number series. The following code snippet for same.

using System.Collections.Generic;  
   
namespace TupleApp  
{  
    class Operation  
    {  
        internal int  FindMinMax(List<int> list, out  int min)  
        {  
            int maximum = int.MinValue, minimum = int.MaxValue;  
            list.ForEach(n =>  
            {  
                minimum = n < minimum ? n : minimum;  
                maximum = n > maximum ? n : maximum;  
            });  
            min = minimum;  
            return maximum;  
        }  
    }  
}

As per the above code snippet, the method returns a value which holds an in variable named maximum. That value is a maximum number from series. This method takes out parameter as an argument named min which holds a minimum value from series.

Now, call this method from an executable program as per the following code snippet.

using System;  
using System.Collections.Generic;  
using System.Linq;  
using static  System.Console;  
   
namespace TupleApp  
{  
    class Program  
    {  
        static void  Main(string[] args)  
        {  
            List<int> numbers = Enumerable.Range(1, 100).OrderBy(x => Guid.NewGuid()).Take(10).ToList();  
            int minimum = 0, maximum = 0;  
            Operation operation = new  Operation();  
            maximum = operation.FindMinMax(numbers, out  minimum);  
            Write($"{minimum} is min and {maximum} is max in {String.Join(",", numbers)}");  
            Read();  
        }  
    }  
}

Now, run the application. The result shows as in the below figure.

Figure 1: Output

It’s right approach but out parameter doesn’t work with async method.

Using Class/Struct

There is another option to get multiple values from a method - create a class or struct with that data structure. We perform the same operation here as well. We create a struct named CalculateData which has two properties to holds maximum and minimum number from a series. The following code snippet is used for the same struct.

namespace TupleApp  
{  
    struct CalculateData  
    {  
        public int  Minimum { get; set; }  
        public int  Maximum { get; set; }  
    }  
}

Now, let’s create another class named Operation which holds a method to find a minimum and maximum number from number series. The following code snippet can be used for the same.

using System.Collections.Generic;  
   
namespace TupleApp  
{  
    class Operation  
    {  
        internal CalculateData FindMinMax(List<int> list)  
        {  
            int maximum = int.MinValue, minimum = int.MaxValue;  
            list.ForEach(n =>  
            {  
                minimum = n < minimum ? n : minimum;  
                maximum = n > maximum ? n : maximum;  
            });  
            CalculateData data = new  CalculateData  
            {  
                Minimum = minimum,  
                Maximum = maximum  
            };  
            return data;  
        }  
    }  
}

As per the above code snippet, the method returns an object which has two properties. These properties hold maximum and minimum values from series.

Now, call this method from an executable program, as per the following code snippet.

using System;  
using System.Collections.Generic;  
using System.Linq;  
using static  System.Console;  
   
namespace TupleApp  
{  
    class Program  
    {  
        static void  Main(string[] args)  
        {  
            List<int> numbers = Enumerable.Range(1, 100).OrderBy(x => Guid.NewGuid()).Take(10).ToList();        
            Operation operation = new  Operation();  
            CalculateData data = operation.FindMinMax(numbers);  
            Write($"{data.Minimum} is min and {data.Maximum} is max in {String.Join(",", numbers)}");  
            Read();  
        }  
    }  
}

Now, run the application. The end result shows as in the below figure.

Figure 2: Output

Using Tuple

The C# 7 introduced new way to define Tuple. Tuple is another option to get multiple values from a method. It can hold multiple heterogeneous values. To use Tuple in the application, we need to install System.ValueTuple NuGet package.

Figure 3 NuGet Package

We perform the same operation here as well. Let’s create a class named Operation which holds a method to find a minimum and maximum number from number series. The following code snippet is used for the same.

using System.Collections.Generic;  
   
namespace TupleApp  
{  
    class Operation  
    {  
        internal (int, int) FindMinMax(List<int> list)  
        {  
            int maximum = int.MinValue, minimum = int.MaxValue;  
            list.ForEach(n =>  
            {  
                minimum = n < minimum ? n : minimum;  
                maximum = n > maximum ? n : maximum;  
            });  
            return (minimum, maximum);  
        }  
    }  
}

As per the above code snippet, the method returns a tuple which has two items. These items hold maximum and minimum values from number series.

Now, calls this method from an executable program as per the following code snippet.

using System;  
using System.Collections.Generic;  
using System.Linq;  
using static  System.Console;  
   
namespace TupleApp  
{  
    class Program  
    {  
        static void  Main(string[] args)  
        {  
            List<int> numbers = Enumerable.Range(1, 100).OrderBy(x => Guid.NewGuid()).Take(10).ToList();  
            Operation operation = new  Operation();  
            (int, int) data = operation.FindMinMax(numbers);  
            Write($"{data.Item1} is min and {data.Item2} is max from {String.Join(",", numbers)}");  
            Read();  
        }  
    }  
}

As per the above code snippet, the method named FindMinMax calls and returns a tuple. When method directly returns more than one values into a Tuple type, it gives them some default name as per their order so as to call them easily. This tuple has two items so these items call Item1 and Item2. Item1 represents first value while Item2 represent second value.Tupple items are used in the same sequence which they are created in.

Now, run the application. The final result shows as in the below figure.

Figure 4 Output

As Item1 and Item2 don’t represent actual names of fields, so we can define custom names of them. Tuple type variables can have custom names instead of Item1 or Item2.

Let’s update existing method named FindMinMax in the Operation class. We assign custom names to those tuple fields. The following code snippet is used for the same.

using System.Collections.Generic;  
   
namespace TupleApp  
{  
    class Operation  
    {  
        internal (int Minimum, int Maximum) FindMinMax(List<int> list)  
        {  
            int maximum = int.MinValue, minimum = int.MaxValue;  
            list.ForEach(n =>  
            {  
                minimum = n < minimum ? n : minimum;  
                maximum = n > maximum ? n : maximum;  
            });  
            return (minimum, maximum);  
        }  
    } 
}

Here, the first field of the tuple has name Minimum while another field has name Maximum.

Now, call this method from an executable program as per the following code snippet.

using System;  
using System.Collections.Generic;  
using System.Linq;  
using static  System.Console;  
   
namespace TupleApp  
{  
    class Program  
    {  
        static void  Main(string[] args)  
        {  
            List<int> numbers = Enumerable.Range(1, 100).OrderBy(x => Guid.NewGuid()).Take(10).ToList();  
            Operation operation = new  Operation();  
            var data = operation.FindMinMax(numbers);  
            Write($"{data.Minimum} is min and {data.Maximum} is max from {String.Join(",", numbers)}");  
            Read();  
        }  
    }  
}

The method named FindMinMax calls and returns a tuple. This tuple has two items that call Minimum and Maximum values as per the sequence of tuple items.

Now, run the application and see the result.

Figure 5 Output

Conclusion

Tuple is an ordered sequence of heterogeneous objects. It is used when a method is required to return more than one values.Tuple instance has fixed number of items. Tuples have a limit of 8 items. If we want to create a Tuple with more items, we have to create nested Tuples. The eighth item of a Tuple should necessarily be another Tuple.

See Also

There are some more article related C#. These are:

  1. C# 7 : Func, Action And Local Function
  2. C# : Why Use Property
  3. C#: Dependency Injection In Console Application