IanG on Tap

Ian Griffiths in Weblog Form (RSS 2.0)

Blog Navigation

July (2014)

(5 items)

April (2014)

(1 item)

March (2014)

(1 item)

January (2014)

(2 items)

November (2013)

(2 items)

July (2013)

(4 items)

April (2013)

(1 item)

February (2013)

(6 items)

September (2011)

(2 items)

November (2010)

(4 items)

September (2010)

(1 item)

August (2010)

(4 items)

July (2010)

(2 items)

September (2009)

(1 item)

June (2009)

(1 item)

April (2009)

(1 item)

November (2008)

(1 item)

October (2008)

(1 item)

September (2008)

(1 item)

July (2008)

(1 item)

June (2008)

(1 item)

May (2008)

(2 items)

April (2008)

(2 items)

March (2008)

(5 items)

January (2008)

(3 items)

December (2007)

(1 item)

November (2007)

(1 item)

October (2007)

(1 item)

September (2007)

(3 items)

August (2007)

(1 item)

July (2007)

(1 item)

June (2007)

(2 items)

May (2007)

(8 items)

April (2007)

(2 items)

March (2007)

(7 items)

February (2007)

(2 items)

January (2007)

(2 items)

November (2006)

(1 item)

October (2006)

(2 items)

September (2006)

(1 item)

June (2006)

(2 items)

May (2006)

(4 items)

April (2006)

(1 item)

March (2006)

(5 items)

January (2006)

(1 item)

December (2005)

(3 items)

November (2005)

(2 items)

October (2005)

(2 items)

September (2005)

(8 items)

August (2005)

(7 items)

June (2005)

(3 items)

May (2005)

(7 items)

April (2005)

(6 items)

March (2005)

(1 item)

February (2005)

(2 items)

January (2005)

(5 items)

December (2004)

(5 items)

November (2004)

(7 items)

October (2004)

(3 items)

September (2004)

(7 items)

August (2004)

(16 items)

July (2004)

(10 items)

June (2004)

(27 items)

May (2004)

(15 items)

April (2004)

(15 items)

March (2004)

(13 items)

February (2004)

(16 items)

January (2004)

(15 items)

Blog Home

RSS 2.0

Writing

Programming C# 5.0

Programming WPF

Other Sites

Interact Software

C# 3.0 Lambdas and Type Inference

Monday 17 March, 2008, 04:07 PM

Daniel Cazzulino recently wrote a blog entry whose main focus was on building pipelines using iterators in C#. Towards the end he showed a slightly irritating problem in C# 3.0. He wanted to write this:

var transformer = x => new { Original = x, Normalized = x.ToLower() };

However, the C# compiler complains because it doesn’t have enough information to infer the type of the transformer variable. The problem it reports is “Cannot assign lambda expression to an implicitly-typed local variable”.

Daniel doesn’t present a working solution to this particular problem – he ends up structuring his program differently to avoid the issue entirely. But in his discussion of this problem, he proposes something that he describes as ugly, and which, as he points out, doesn’t work anyway:

Func<string, {string Original, string Normalized}> transformer =
   x => new { Original = x, Normalized = x.ToLower() };

This is a direct approach to the problem described in the compiler error message. Can’t assign the expression to an implicitly-typed variable? OK, let’s make the variable explicitly typed. Unfortunately, you can’t specify the type because the expression involves an anonymous type. And that’s the thing about anonymous types: they don’t have names.

Daniel has made up a plausible syntax for denoting unnamed types: the first part in {} shows a possible solution. But that was just a hypothetical suggestion on his part – in fact C# 3.0 doesn’t provide a way to denote anonymous types.

But there is a solution. We carry on using an implicitly-typed variable, and fix the expression instead. The error says we can’t use a lambda expression. OK – let’s use something else. And as you’ll see, we don’t even have to get rid of the lambda. We can just wrap it in something.

Why Can’t I Use a Lambda?

To decide what to use in place of the raw lambda expression, we need to understand why C# isn’t letting us use a lambda here. The problem is that lambda expressions don’t have an intrinsic type. They’re more adaptable than that – a given lambda expression could mean several different things. The most straightforward demonstration of this is that the exact same expression could evaluate to either a delegate or an expression tree.

The compiler uses the context to determine the type. If you’re trying to assign or pass the lambda to something expecting a delegate, it’ll turn into a delegate. But if the target expects an expression tree, you’ll get one of those instead.

In short, a lambda’s expression’s evaluated type is determined by the context in which it’s used.

This gives us a problem with var: var says that its type is determined by the expression with which it is initialized. So when var meets a lambda, it’s like the two are stood by a doorway, each politely saying “No, after you”. (Apologies to my international readers – I suspect that might be a slightly over-British analogy...)

Something needs to decide the type. But the obvious approaches (ordinary explicitly-typed variables, or casts) end up hitting the problem Daniel hit: you can’t denote an anonymous type, so how do you specify the type? But it turns out that you don’t need to specify the type completely. All you really need to do is provide just enough information to let the C# compiler proceed.

Providing Just Enough Type Information

We can narrow down the C# compiler’s options without fully specifying the type. The trick is to go via a function call. Consider this apparently pointless function:

public static Func<T, TResult> Funcify<T, TResult>(Func<T, TResult> f)
{ return f; }

What use would that be, you may wonder? It takes any single-parameter function and returns that function without doing anything with or to it!

However, this provides the C# compiler with a little more information. If I pass a lambda as a parameter to Funcify, I’ve closed down an option: the C# compiler knows that whatever it produces needs to be a Func – it no longer has the option to produce an expression tree. This might be enough to disambiguate matters. Unfortunately, it’s not quite enough to fix our example, as we’ll see when we try it:

var transformer = Funcify(
      x => new { Original = x, Normalized = x.ToLower() });

This gets rid of the previous error, but replaces it with a new one:

The type arguments for method 'Funcit.Program.Funcify<T,TResult>(System.Func<T,TResult>)' cannot be inferred from the usage. Try specifying the type arguments explicitly.

But that’s progress. Honest! The compiler is no longer telling us that we can’t do this with var. It’s now telling us that it doesn’t have quite enough information.

The problem here is that it doesn’t know what ‘x’ is. And how could it? Any type with a ToLower method would do. The intent here is for it to be a string, so we just need to express that:

var transformer = Funcify(
      (string x) => new { Original = x, Normalized = x.ToLower() });

And now we’re good. The compiler is happy, because we gave just enough information to pin things down and it was able to infer the rest.

Mumble Types

I’ve seen in some C# team members’ blogs a suggestion for something they call ‘mumble types’. If I’ve understood them correctly, the idea is that you can provide a type specification, but you get to ‘mumble’ (i.e. be unclear) about parts of the type specification. This would give us an alternative solution:

Func<string, ?> transformer =
      x => new { Original = x, Normalized = x.ToLower() };

This doesn’t work today, but I would prefer this solution if it were available. It does exactly what I did – it lets me specify just enough to let the compiler’s type inference finish the job – but it doesn’t require the questionable hack of my Funcify function. And I think it’s clearer – with my example, it’s not particularly obvious that I was trying to fix some parts of the type specification while leaving other parts to be inferred. But with this ‘mumble type’ approach, it’s a lot more obvious that I’m saying ‘I want it to be a Func, and I want the input to be a string, but I want the compiler to infer the Func’s return type’. Also, this approach avoids the clutter of specifying the string type in the lambda parameter list itself, so I find it somewhat more aesthetically pleasing.

The use of the ‘?’ is based on what I’ve seen in C# team members’ blogs in the past year or two. However, here’s a different syntax to consider:

Func<string, var> transformer =
      x => new { Original = x, Normalized = x.ToLower() };

We already use the keyword var to say ‘the compiler should deduce this type’ for variable declarations. So I think it would be consistent to use the same keyword to mean the same thing in partially specified generic types too. That said, the ‘?’ has the benefit of standing out. And it seems reminiscent of Haskell’s use of ‘_’ to mean ‘whatever’. So I could see either approach, but I think I slightly prefer the idea of using var.

Gratuitous Plug for Training in London

And finally, some advertising. I’m teaching a couple of training courses for Pluralsight in London soon. I’ll be running the Silverlight course that Fritz Onion and I co-author at Old Street from 31st March to 3rd April. And I’ll be teaching our WPF course at the same location the following week – from 7th to 10th April.

Copyright © 2002-2013, Interact Software Ltd. Content by Ian Griffiths. Please direct all Web site inquiries to webmaster@interact-sw.co.uk