A Tipple with a Tuple

One of the most controversial and questioned data types available to the C# developer is the "Tuple." A data type (actually a class) in the System name space, the Tuple has been the subject of debate, discouragement, and downright humiliation since it first saw the light of day.

Why, though, would one data type cause so much pain for us humble developers? Well, it all lies with the fact of just what a Tuple is.

A Tuple, it happens, is kind of like a dynamic class that has a limited number of properties that are in strict order. In the case of .NET, it has an upper limit of 7.

As way of an example, let's take a look at the following example, which comes straight from the MSDN documentation.

using System;

namespace Tuples
{
   class Program
   {
      static void Main()
      {

         var primes = Tuple.Create(2, 3, 5, 7, 11, 13, 17, 19);

          Console.WriteLine("Prime numbers less than 20: " +
            "{0}, {1}, {2}, {3}, {4}, {5}, {6}, and {7}",
            primes.Item1, primes.Item2, primes.Item3,
            primes.Item4, primes.Item5, primes.Item6,
            primes.Item7, primes.Rest.Item1);
      }
   }
   }

When this is compiled and run, you'll get the following output:

Tuple
Figure 1: Listing of the prime numbers less than 20

Nothing complicated here, right?

Look closely at the source code, though. You'll quickly see that the items added in the Tuple's constructor are available via the properties 'Item1' through 'Item7' with anything further being available via the 'Rest' property (more on that soon).

What we essentially have here is a class with seven named properties, that can be used everywhere you would use a normal class, in the same manner as a normal class.

It's not beyond the realms of possibility to write an entire application using nothing but Tuples to represent your application objects. The reality, however, is that it would be an absolute maintenance nightmare if you did.

This very subject about using Tuples rather than correctly defined classes is one of the main reasons why Tuples have such a bad name and more than a fair few beginners have used them in such a way before they've learned how to do proper OOP-based class design when starting out in C#.

If Tuples are such a bad idea, why where they added to C# in the first place?

Well, it turns out there are a few cases where these things are genuinely useful. The first and probably most obvious case is in database record access. When reading ADO.NET data readers, you could, for instance, do the following:

DbCommand command = new SqlCommand("select * from foo",
   new SqlConnection());
using (DbDataReader reader = command.ExecuteReader())
{
   reader.Read();
   var dbRecord = Tuple.Create(reader[0], reader[1],
                  reader[2], reader[3]);
   }

Allowing you to then access that record as:

Console.WriteLine(dbRecord.Item1);
Console.WriteLine(dbRecord.Item2);
Console.WriteLine(dbRecord.Item3);
Console.WriteLine(dbRecord.Item4);

This might come in handy for very simple scenarios or in cases where you don't know the actual output of the database record you're retrieving.

In a similar vein, you may find it useful to provide a level of generic access to unknown data sources.

I myself have used this approach with communications software when dealing with binary SMS text messages.

However, one place I found it very, very useful recently was in a Web application I was developing. As many of my regular readers may know, I'm a big fan of Nancy, and I've even written a book on it; it's available in the Syncfusion free eBook series.

One of the great things I like about Nancy is the ease with which you can return JSON-formatted data to your Web-based user interface. It's as simple as this:

private dynamic Index(dynamic paramaters)
{
   return Response.AsJson(new {Foo = 1, Bar = "Hello"});
}

This will result in your AJAX call receiving the following:

{ "Foo":1, "Bar": "Hello" }

Directly in a format that JavaScript natively understands.

Generally, however, you only have one object available to return or a specifically defined set; for example:

private dynamic Index(dynamic paramaters)
{
   PageTitle title = new PageTitle
   {
      MainTitle = "Foo",
      SubTitle = "Bar"
   };
   return Response.AsJson(title);
}

You can't, however, return multiple objects, unless you combine them into a higher level object; for example:

      private dynamic Index(dynamic paramaters)
      {
         PageTitle title = new PageTitle
         {
            MainTitle = "Foo",
            SubTitle = "Bar"
         };

         PageTitle title2 = new PageTitle
         {
            MainTitle = "Foo2",
            SubTitle = "Bar2"
         };

         Combiner combiner = new Combiner
         {
            Title1 = title,
            Title2 = title2
         };

         return Response.AsJson(combiner);
      }


   }

   public class Combiner
   {
      public PageTitle Title1 { get; set; }
      public PageTitle Title2 { get; set; }
   }

As you can see, the code is starting to get a bit long here.

Fear not, though, because this is exactly where the Tuple excels. We now can rewrite our previous Nancy handler as follows:

   private dynamic Index(dynamic paramaters)
   {
      var combiner = Tuple.Create(
         new PageTitle
         {
            MainTitle = "Foo",
            SubTitle = "Bar"
         },

         new PageTitle
         {
            MainTitle = "Foo2",
            SubTitle = "Bar2"
         });

         return Response.AsJson(combiner);
      }

The best part about this is that each item can be ANY type of object, not just the classes here that I've used as an example.

In the first combiner, your two class types could only ever be 'PageTitle' type objects. By using a Tuple, you can assign and re-assign in a very dynamic fashion, and ALL without using dynamic language typing, casting, or generics.

Tuples, at the end of the day, are like any tool in your C# toolbox. They're there for the circumstances that need them, and can be safely stowed away when you don't.



About the Author

Peter Shaw

As an early adopter of IT back in the late 1970s to early 1980s, I started out with a humble little 1KB Sinclair ZX81 home computer. Within a very short space of time, this small 1KB machine became a 16KB Tandy TRS-80, followed by an Acorn Electron and, eventually, after going through many other different machines, a 4MB, ARM-powered Acorn A5000. After leaving school and getting involved with DOS-based PCs, I went on to train in many different disciplines in the computer networking and communications industries. After returning to university in the mid-1990s and gaining a Bachelor of Science in Computing for Industry, I now run my own consulting business in the northeast of England called Digital Solutions Computer Software, Ltd. I advise clients at both a hardware and software level in many different IT disciplines, covering a wide range of domain-specific knowledge—from mobile communications and networks right through to geographic information systems and banking and finance.

Related Articles

Comments

  • Reply

    Posted by Dhiya on 07/21/2016 04:46am

    Here i had read the content you had posted. It is much interesting so please keep update like this.

    Reply
  • I've used them as simple DTOs myself.

    Posted by Gavin Lanata on 07/17/2016 08:31am

    My most recent use for this is via an inter-object messaging system. In the message I would use a tuple. Commonly the first item would be an int which I would use a switch statement in the receiving object to decided what to do. Then item 2 would be what ever the data was to be passed.

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date