I have seen the Tuple introduced in .Net 4 but I am not able to imagine where can be it be used. We can always make a Custom class or Struct.
Edit: I am looking for an example which can also be considered inside the bracket of best practices.
I have seen the Tuple introduced in .Net 4 but I am not able to imagine where can be it be used. We can always make a Custom class or Struct.
Edit: I am looking for an example which can also be considered inside the bracket of best practices.
That's the point - it is more convenient not to make a custom class or struct all the time. It is an improvement like Action
or Func
... you can make this types yourself, but its convenient that they exist in the framework.
Here's a small example - say you have a method that needs to lookup a user's handle and email address, given a user Id. You can always make a custom class that contains that data, or use a ref / out parameter for that data, or you can just return a Tuple and have a nice method signature without having to create a new POCO.
public static void Main(string[] args)
{
int userId = 0;
Tuple<string, string> userData = GetUserData(userId);
}
public static Tuple<string, string> GetUserData(int userId)
{
return new Tuple<string, string>("Hello", "World");
}
Tuples are heavily used in functional languages which can do more things with them, now F# is a 'official' .net language you may want to interoperate with it from C# and pass them between code written in two languages.
C#'s tuple syntax is ridiculously bulky, so tuples are painful to declare. And it doesn't have pattern matching, so they're also painful to use.
But occasionally, you just want an ad-hoc grouping of objects without creating a class for it. For example, let's say I wanted to aggregate a list, but I wanted two values instead of one:
// sum and sum of squares at the same time
var x =
Enumerable.Range(1, 100)
.Aggregate((acc, x) => Tuple.Create(acc.Item1 + x, acc.Item2 + x * x));
Instead of combining a collection of values into a single result, let's expand a single result into a collection of values. The easiest way to write this function is:
static IEnumerable<T> Unfold<T, State>(State seed, Func<State, Tuple<T, State>> f)
{
Tuple<T, State> res;
while ((res = f(seed)) != null)
{
yield return res.Item1;
seed = res.Item2;
}
}
f
converts some state into a tuple. We return the first value from the tuple and set our new state to the second value. This allows us to retain state throughout the computation.
You use it as such:
// return 0, 2, 3, 6, 8
var evens =
Unfold(0, state => state < 10 ? Tuple.Create(state, state + 2) : null)
.ToList();
// returns 0, 1, 1, 2, 3, 5, 8, 13, 21, 34
var fibs =
Unfold(Tuple.Create(0, 1), state => Tuple.Create(state.Item1, Tuple.Create(state.Item2, state.Item1 + state.Item2)))
.Take(10).ToList();
evens
is fairly straightforward, but fibs
is a little more clever. Its state
is actually a tuple which holds fib(n-2) and fib(n-1) respectively.
There's an excellent article in MSDN magazine that talks about the belly-aching and design considerations that went into adding Tuple to the BCL. Choosing between a value type and a reference type is particularly interesting.
As the article makes clear, the driving force behind Tuple was so many groups inside of Microsoft having a use for it, the F# team up front. Although not mentioned, I reckon that the new "dynamic" keyword in C# (and VB.NET) had something to do with it as well, tuples are very common in dynamic languages.
It is otherwise not particularly superior to creating your own poco, at least you can give the members a better name.
I used a tuple to solve Problem 11 of Project Euler:
class Grid
{
public static int[,] Cells = { { 08, 02, 22, // whole grid omitted
public static IEnumerable<Tuple<int, int, int, int>> ToList()
{
// code converts grid to enumeration every possible set of 4 per rules
// code omitted
}
}
Now I can solve the whole problem with:
class Program
{
static void Main(string[] args)
{
int product = Grid.ToList().Max(t => t.Item1 * t.Item2 * t.Item3 * t.Item4);
Console.WriteLine("Maximum product is {0}", product);
}
}
I could have used a custom type for this, but it would have looked exactly like Tuple.
A few examples off the top of my head:
For example you wouldn't want to include System.Drawing in a web application just to use Point/PointF and Size/SizeF.