.NET 3.5: Lambda Expressions, Type Inference, and Anonymous Methods
November 20, 2007 4:33 pm programmingAs of v2.0, .NET already had support for first-class function types through delegates. v3.5 adds in a new concise syntax for creating short delegates.
public void performOnAllMembers(Action<Foo> action) {
foreach( Foo foo in datastructure ) {
action(foo);
}
}
// Old syntax
performOnAllMembers(delegate(Foo foo) {
foo.bar();
});
// New Lambda Syntax
performOnAllMembers( foo => foo.bar() );
Besides shortening “delegate” to “=>”, most of the keyboard savings here comes from type inference; you no longer have to declare that “foo” is a “Foo” since performOnAllMembers() already declares that it needs an Action to perform on a Foo. Note that this is just an assumption in the source code; everything is still strongly typed and the compiler will complain if you pass anything that’s not compatible with “Foo”.
Too Much Type Hiding?
While the source code does look cleaner, I generally believe explicitness is a virtue, and type inference works against that. If you don’t happen to have the method signature/documentation/source code for performOnAllMembers() handy, then you might be left wondering exactly of what type foo is and what it’s capable of. That means that you have to interrupt your flow of reading the source to go and look up the performOnAllMembers() contract; this interruption can only hurt your ability to understand what’s going on. The relaxed-typing proponents claim that this isn’t a big deal; I haven’t had a lot of experience with non-strong typing so I’m cautiously withholding judgment.
Anonymous Types
.NET 3.5 takes type inference one step further with anonymous types. These are similar to the Java anonymous inner types, except with a better syntax:
var myReference = new { Foo = "foo", Bar = 1 };
myReference points a instance with a strong type, and behaves as such; the type name is just hidden. Combined with the new property initialization syntax, .NET comes very close to having tuples. However, there’s a big catch with anonymous types: they’re only valid as local variables. That means you can’t pass them as parameters, get them as return values, or use them as generic type parameters (which means they can’t be stored in generic collections except as Objects). Moreover it doesn’t appear that they can ever be given methods; they’re basically local, dynamically generated structs (and I mean C dumb structs, not C# wannabe-classes structs).
There’s also something to do with lambda expressions called “Expression Trees”. I haven’t investigated this in detail yet, but it looks promising. Scott Guthrie has more to say on it. I’ll probably post more once I read up on it.
