C# : Some reservations against Tuple

Tuple is a new type that was introduced in the .Net 4 framework. So it’s not a feature of C# per se, but rather another class in the framework and thus available to other languages as well.

Tuple allows you to group together elements without the need to create a new class. It can be used to reduce parameter lists to one argument, convert many out parameters into a single Tuple parameter or to create a simple inner type in a class without resorting to creating an actual class.

I am not sold on Tuple. It does have it’s uses, but for the most common scenarios I have reservations on it’s use.

Let’s start with a contrived example that use the Tuple type.

using System;
using System.Linq;

namespace TupleExamples
{
    public class TupleExamples
    {
        public void CallingMethod()
        {
            Tuple<string, decimal, bool> cheapestBook = GetCheapestBook();

            if (cheapestBook.Item3)
            {
                Console.WriteLine("We have it in stock!");
                Console.WriteLine("Product name : " + cheapestBook.Item1);
                Console.WriteLine("Product price : " + cheapestBook.Item2);
            }
        }

        private Tuple<string, decimal, bool> GetCheapestBook()
        {
            var books = from product in Product.Products()
                        where product.Type == ProductType.Book
                        orderby product.Price
                        select Tuple.Create(product.Name, product.Price, product.InStock);

            return books.First();
        }
    }
}

My reservations about Tuple are as follows:

  • You access the elements of a Tuple using methods named Item1, Item2, … These are very opaque. In my example, it is hard to glean meaning from if (cheapestBook.Item3).
  • The description of the Tuple itself with it’s generic type parameters isn’t very meaningful. In the type declaration Tuple, the reader has no clue as to what each type parameter (string, decimal and bool) represent.

Here is the same example using a private inner class instead of a Tuple.

using System;
using System.Linq;

namespace TupleExamples
{
    public class NonTupleExamples
    {
        public void CallingMethod()
        {
            Book cheapestBook = GetCheapestBook();

            if (cheapestBook.InStock)
            {
                Console.WriteLine("We have it in stock !");
                Console.WriteLine("Product name : " + cheapestBook.Name);
                Console.WriteLine("Product price : " + cheapestBook.Price);
            }
        }

        private Book GetCheapestBook()
        {
            var books = from product in Product.Products()
                        where product.Type == ProductType.Book
                        orderby product.Price
                        select new Book()
                        {
                            Name = product.Name,
                            Price = product.Price,
                            InStock = product.InStock
                        };

            return books.First();
        }

        private class Book
        {
            public string Name { get; set; }
            public decimal Price { get; set; }
            public bool InStock { get; set; }
        }
    }
}

While the code is a bit longer, it is much more readable. if (cheapestBook.InStock) beats out if (cheapestBook.Item3) for clarity.

I searched on blogs and Stackoverflow for other uses of Tuple. Two of these that came up from credible sources were :

  1. When inter-operating with a dynamic language that has a Tuple concept (namely Python).
  2. When the pieces of data returned by a method are unrelated to each other and thus do not fit conceptually in a class.

The second use begs the question: why? A method that needs to group together unrelated pieces of data that do not fit together sounds like bad design. Of course there will always be situations where a quick Tuple will do the job, but for clarity I will avoid it in many instances where it could be used.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s