A genealogy tour in .NET: lady

March 8, 2009 20:00
To bring up a lady, start from her grandmother.
Eric Berne.

Anonymous types are nice since you write less code. You don't declare a class, and don't put its name when you create it. However, using them anywhere outside small Linq-like filterings is stultifying and dangerous (think about ASP.NET MVC here).  

But species transform themselves generation after generation, and so do software artifacts. As a corollary of this axiom, anonymous types of .NET 3.5 are about to give birth to another abstraction of .NET 4.0 [1]. Ladies and gentlemen, please make her feel welcome: Tuple, The Lady!

Where do we come from.

Well, how do you return two values from a method?

public int ReturnTwoValues(out string param)
{
  param = "foo";
  return 123;
}


This is sort of clumsy, and it all gets worse if you need to return more values from a method. To avoid having multiple out parameters you have two options. First off, you can create a separate (throwaway and dull) type just for that bulk of output. Alternatively, you can resort to a nefarious trick of having a few "class level" properties that get updated from your method.

But there's C#4 in the offing, with another option
.

Or maybe not.


Um, chances are tuples won't be publicly available in BCL. The idea comes from functional languages and those have a good and brief syntax for them, but apparently C# couldn't provide anything decent. Geeky languages like F# make use of tuples from the get go; however high-fed C# developers would have to fallback to an approach that is shown below, and perhaps they would not like it.

C# version.

Tuple is a generic type that just contains some unstructured data [2]. So we write

public Tuple<string, int> ReturnTwoParams()
{
  return new Tuple("foo", 123);
}
...
 
var result = ReturnTwoParams();
string first = result.First;
int second = result.Second;


Where Tuple types are defined as

public class Tuple<T1> 
{
  public readonly T1 First;
  public Tuple(T1 t1) { First = t1; }
  //overrides for Equals, GetHashCode, etc
}
 
public class Tuple<T1, T2> : Tuple<T1> 
{
  public readonly T2 Second;
  public Tuple(T1 t1, T2 t2) : base(t1) { Second = t2; }
  //overrides for Equals, GetHashCode, etc
}
...

 
Classes vs Structs.

As you see, tuples (as well as anonymous types) are immutable. That makes it possible to use a tuple as a hashtable key, and simplifies its usage in multithreaded code and closures. The implementation above uses classes because it's stolen from Luca Bolognese's blog and because structs slow down performance if they grow just a bit more than 16 bytes. That means a value type tuple with 3 or more parameters is probably ineffective.

However, Common Generics Library from ECMA C# and CLI Standards uses structs in their implementation [3].

You also may have seen custom implementations where tuples with less than 3 parameters were structs, and others were classes - that's interesting too, though brings its own issues.



Footnotes.

[1] - Here's What's New in the BCL in .NET 4.0 from Justin Van Patten.

[2] - It's probably better to read someone more conversant in tuples than yours truly.

[3] - Common Generics Library is a very interesting thing, the pdf is quite big and academic but they have code.

 


Comments

Comments are closed