tags:

views:

170

answers:

4

I am making an instructional video for C# 4.0 for beginning programmers.

For every topic I introduce I include a practical example which the student could actually use, for instance, for the improved COM Interop functionality, I show how to create an Excel file and fill it with values from code.

For named and option parameters I show how you can create a logging method with 5 parameters but don't have to pass any if you don't want since they all have default values. So they see how calling methods is easier with this feature.

I would also like to introduce tuples as well if I can, but it seems that all the "practical examples" (as in this question: http://stackoverflow.com/questions/2745426/practical-example-where-tuple-can-be-used-in-net-4-0) are very advanced. The learners that use the video learn OOP, LINQ, using generics, etc. but e.g. functional programming or "solving Problem 11 of Project Euler" are beyond the scope of this video.

Can anyone think of an example where tuples would actually be useful to a beginning programmer or some example where they could at least understand how they could be used by and advanced programmer? Their mechanics are quite straight-forward for a beginning programmer to grasp, I would just like to find an example so that the learner could actually use them for a practical reason. Any ideas?

Here's what I have so far, but it is just dry mechanics without any functionality:

using System;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            //two ways to define them
            var customer = new Tuple<int, string, string>(23, "Sam", "Smith");
            var customer2 = Tuple.Create<int, string, string>(34, "James", "Allard");

            //with type inference, more concise (only available with the Create keyword)
            var customer3 = Tuple.Create(23, "John", "Hoopes");

            //you can go up to eight, then you have to send in another tuple
            var customer4 = Tuple.Create(1, 2, 3, 4, 5, 6, 7, Tuple.Create(8, 9, 10));

            Console.WriteLine(customer.Item1);
            Console.WriteLine(customer2.Item2);
            Console.WriteLine(customer3.Item3);
            Console.WriteLine(customer4.Rest.Item1.Item3);

            Console.ReadLine();
        }
    }
}
+5  A: 

The best practical reason i can see is using them as temporary "classes". You want to associate multiple pieces of information, but not create yet another class structure to hold them.

They should be temporary, because if you're using them a lot, you should be going all the way and properly creating classes...

I can't think of a good specific example, i've mostly used them for small things, like temporary maps that need a single key but multiple pieces of information in the value...

John Gardner
+8  A: 

Tuples are not necessarily the first topic I would tackle for beginner programmers ... however, there are some simple examples.

One that comes to mind is returning a value (which may actually be null) from a function that performs a search (or calculation), together with a boolean that indicates whether the result was found or not. It's an approach that avoids using out parameters, which can be cumbersome or problematic in certain scenarios (like LINQ queries):

public Tuple<string,bool> SearchDictionary( string searchKey )
{
    string value;
    bool wasFound = someDictionary.TryGetValue( searchKey, out value );
    return new Tuple<string,bool( value, wasFound );
}

// since <null> is a legal value to store in the dictionary, we cannot
// use it to distinguish between 'value not found' and 'value is null'.
// the Tuple<string,bool>, however, does allow us to do so...
var result = SearchDictionary( "somekey" );
if( result.Item2 )
{
    Console.WriteLine( result.Item1 );
}

Another example that I think is natural, is creating associations between two values without creating an explicit class for the purpose. For example, let's imagine we want to represent pairs of opponents who will play tennis matches. We could use:

// note the symmetry in the representation of opponents of a tennis match...
// if the relationship were asymmetrical, tuple may not be the best choice.
var playerA  = new TennisPlayer("Serena Williams");
var playerB  = new TennisPlayer("Venessa Williams");
var match    = new Tuple<TennisPlayer,TennisPlayer>( playerA, playerB );

Creating a class for something like this can be avoided by using tuples instead.

A final example, is using tuples to represent composite keys in a dictionary. Since Tuple<>s can be compared to one another for equality, it becomes possible to do stuff like:

var complexDictionary = 
      new Dictionary<Tuple<string,int,decimal,DateTime>,string>();
complexDictionary.Add( new Tuple("USA",-4,1.671,DateTime.Now), "active" );

EDIT: One comment I would make when educating developers about the use of tuples, is that tuples should rarely (if ever) appear in the public interface of code you expect others to consume. As tools to simplify the internal implementation of a class or module, I think they're fine. But once you start passing them in or out of methods that developers consuming your code have to interact with, you run in the problem that tuples obscure the semantics of your API. It becomes hard for developers to interpret what Tuple<int,int> is supposed to mean. What do Item1 or Item2 mean in such a case? When you see yourself needing to pass tuples in or out of methods, you should strongly consider writing a class to encapsulate and clarify the relationship.

LBushkin
Very nice, this makes sense, I can build something with this.
Edward Tanguay
I disagree with your coding sample. Having a collections of tuples is confusing. Why not create a class called DoublesTeam and have it take the two tennis players?
Chuck Conway
When consuming the SearchDictionary method, why wouldn't one check the results (string) to make sure it's not null or empty? It would simplify the code and remove the need for the tuple.
Chuck Conway
Isn't that one point of tuples: so that you don't have to explicitly create classes that are temporary anyway?
Edward Tanguay
@Chuck Conway: Keep in mind, my examples are for illustrative purposes here. However, I'll stand by the examples - I think they are reasonable uses of tuples. Creating pairs of items is not uncommon in many programs, and tuples are an effective way of representing that. Whether this would be a good design choice in a real-world application is a different story ... and much would depend on the kind of program being written, who would maintain it, what it's lifetime is anticipated to be, and so on.
LBushkin
@Chuck Conway: With regard to the SearchDictionary example, what would you do if the value `null` is actually ones of the possible legal values that can be stored? You can no longer use `null` to represent "value not found". This is why methods like `Dictionary.TryGetValue()` have an `out` parameter to return the value found and a `bool` as the return value. However, in certain cases (as I mention), out parameters are inconvenient, and tuples make it easy to wrap together the value together with an indicator of whether the search was successful or not. Does that make sense?
LBushkin
@LBushkin Tuples introduce ambiguity. As developer reading some code that contain Tuples it's not immediately apparent what they do. I am force to discover their purpose. It might be as simple as reading a comment. In most cases I have to understand the code around the assignment or I must open the class that created them.
Chuck Conway
A: 

What about on a login form? They see those all of the time.

var loginCredentials = 
    new Tuple<string, SecureString>(nameTextBox.Text, passwordTextBox.Text);

if (Login(loginCredentials))
    Console.Writeline("Login - Success!");
else
    Console.Writeline("Login - Failure");

...

public bool Login(Tuple<string, SecureString> loginCredentials)
{
    return ...
}
SnOrfus
Hhm that example is less clear and actually more text than the two-parameter way :/
lasseespeholt
+2  A: 

I use them in place of private classes. The are great when used internally in a class. Exposing them outside the class only led to confusion. I kept having to open the class to determine what was what.

Chuck Conway