C# 4.0 defines a new types of generics. It is called Tuple. In this article, we will be discussing about this amazing new introduction in the language.
Tuples can be used any where when behavior less and immutable data containers are needed. These containers are allowed to hold up to 8 elements of same or different types. If more than 8 elements are required then 8th element can be defined as another tuple.
Tuple and Anonymous types:
Like anonymous types, we use tuples when we don’t need to define any new behavior to our collection. The disadvantage of using tuple over anonymous type is that we can not assign any meaningful name to any tuple items. They are just named as Item, Item2 and so on. The advantage is that, unlike anonymous types, tuples can be specified as parameter or return type of a method. Before 4.0, we had no options other than using object arrays which have its performance implication due to boxing / unboxing when primitive types is involved.
I don’t think that anonymous type is going anywhere. This is because of its extensive use for writing LINQ queries.
Instantiating a Tuple:
There are two ways to instantiate a tuple.
- Using new Operator
var myTuple = new Tuple<int, int, int>(2, 3, 4);
Tuple<int, int> myTuple2 = new Tuple<int, int>(2, 3);
- Using Create factory method available in the Tuple class itself.
var myTestTuple = Tuple.Create<int, int>(1, 2);
Comparing two tuples:
Equals method has been overloaded for Tuple. To compare between two tuples, each member is matched with the member in the corresponding member in the other one if possible.
Tuple<int, int> myTuple2 = new Tuple<int, int>(2, 3);
Tuple<int, int> myTuple3 = new Tuple<int, int>(2, 3);
if (myTuple2.Equals(myTuple3))
Console.WriteLine("myTuple2.Equals(myTuple3)");
As you might have guessed this would lead to a TRUE condition and myTuple2.Equals(myTuple3) will be printed on the screen.
Equality comparison (= =) operator has not been overloaded to compare individual items. Two tuples are considered equal (for = =) if they reference same tuple object. So, in the following case, nothing will be printed on the screen.
var myTuple2 = new Tuple<int, int>(2, 3);
var myTuple3 = new Tuple<int, int>(2, 3);
if (myTuple2 == myTuple3)
Console.WriteLine("myTuple2 == myTuple3");
Accessing Tuple members:
The members of tuples are called “Items”. These are available through tuple instance. The items are named based on the position they occupy in the tuple e.g. first item is named as Item1, 2nd item is named as Item2 and so on.
var myTuple = new Tuple<int, string>(1, "shujaat");
Console.WriteLine("First Item: " + myTuple.Item1);
Console.WriteLine("Second Item: " + myTuple.Item2);
This might be bad news for people using anonymous types with names as follows:
var myObj = new { TypeId = 1, Name = "shujaat" };
Console.WriteLine("TypeId : " + myObj.Name);
Console.WriteLine("Name : " + myObj.Name);
Iterating through Tuple items:
Since Tuple does not implement IEnumerable interface, the elements can not be enumerated. It can also not be used in foreach loop. Since Tuple is not sealed, so, in case, you want foreach functionality then you can inherit Tuple class and implement the child with IEnumerable interface. As a requirement, you would have to provide definition of GetEnumerator method. Since tuple are not expected to have many items, I think that it should rarely be required iterating through tuple items.
From the above, it is obvious when we use foreach for tuple, it gives error.
You might already know that tuples are available in F# (Functional language from Microsoft). I think that introducing tuples in C# is another injection in C# for making it more functional.