With two posts in as many days, you might get the wrong idea. Let me reassure you: you cannot count on me posting regularly.
That being said, I just found another neat C# abuse and had to share.
It’s occasionally useful (or necessary, or both) to use null as a starting value or to explicitly return a null value. Aside from initializing a local variable, another (more interesting) example of the former is the Enumerable.Aggregate—fold for you functional programmers—overload that takes a seed.
In certain circumstances, specifying null can cause difficulty for the compiler. With the previously referenced method, a null seed will break generic type inference and force you to either:
- cast
nullto the correct type (yuck!) or - explicitly specify the two type arguments (double yuck!)
Casting null is also required when trying to use null as a result for the ternary operator (<condition> ? <true-result> : <false-result>). The compiler needs to know (and verify) the type of that expression, and gripes about “no implicit conversion” when it sees a null literal.
It turns out there’s another option, though.
When the .NET Framework 2.0 introduced generics, there was a need for a way to express the default value for a generic type (since generic types could be either value or reference types). So the default keyword (of switch fame) was overloaded with a new function.
What isn’t explicitly mentioned in that documentation is that you can use default with concrete types, too. And an expression using default is strongly typed.
So, now instead of saying:
(ComplexObject) null
You have the option of saying:
default(ComplexObject)
I’m not sure yet if I actually prefer this to typecasting null. It certainly looks odd, but that could just be unfamiliarity.
But I thought it had potential and wanted to share. Thoughts?
One solution to this problem is to specify the types of the parameters to the lambda expression that is passed to Aggregate. That would a allow the compiler to infer everything properly and you could pass null as the seed parameter. It requires a bit more typing but it looks better.
someList.Aggregate(null, (ComplexObject o, Whatever w) => accumalator-function)
Comment by Dustin Campbell — January 4, 2008 @ 7:06 am
Ah! Of course. Despite the closer similarity to anonymous method syntax (with the delegate keyword), I had completely forgotten lambda expression parameters could be type decorated.
Thanks.
Comment by jacobcarpenter — January 4, 2008 @ 8:07 am
Wow, I didn’t know about default(ComplexType). Typed null
I have a feeling this might also be useful elsewhere besides giving hints to the type-inferencer.
Comment by Kirill Osenkov — January 4, 2008 @ 11:43 am
[...] refer to the type of an anonymous type, you have to provide an example instance. Using an undocumented feature of the default keyword, we can strongly type the properties of our prototype object without a bunch of null [...]
Pingback by Dictionary To Anonymous Type « Jacob Carpenter’s Weblog — March 13, 2008 @ 11:11 am
What’s the undocumented part? The expression default(ty) in described in section 14.5.14 of the C# 2.0 Ecma standard, so I think I’m missing some point here
Comment by Peter Sestoft — July 29, 2008 @ 7:41 am
Wow. Uh, C# Precisely, right? Great book.
Perhaps I indulged in a bit of hyperbole with my link text to this post (from Dictionary to Anonymous type).
But the MSDN documentation is surprisingly deficient when it comes to combining
defaultand concrete types: http://msdn.microsoft.com/en-us/library/25tdedf5.aspxComment by Jacob — July 29, 2008 @ 8:31 am