The big new feature in C# 5 is asynchronous programming support, which I wrote about last week. However, the C# folks have also slipped in a couple of smaller features and I thought I’d round things out by mentioning those.

Method caller information

There’s a complete style guide to be written on Writing Enterprisey Code, but one of my favourite “enterprisey” tells, after the use of Visual Basic, is obsessively logging every function you pass through:

Although this code is efficient and clear by enterprisey standards, with C# 5 it can be even efficienter and clearer. C# 4 introduced optional parameters, which meant callers of a method could leave out the arguments and the compiler would fill in the default values:

With C# 5, you can put a special attribute on an optional parameter and the compiler will fill in the value not with a constant but with information about the calling method. This means we can implement the Logger.Trace to automagically pick up where it’s being called from:

Notice that the parameters to which you apply the attributes must be optional. If they aren’t optional, the C# compiler will require the calling code to provide them, and the provided values will override the defaults.

Another example of how you can use this is in implementing INotifyPropertyChanged without needing either literal strings, expression magic or mystic weavers:

For what it’s worth, you can also get the line number of the calling code using [CallerLineNumber]. This may be useful for diagnostic methods, but if you really need it, that may be a sign that the calling code is just a bit too enterprisey.

Using loop variables in lambdas

Technically, this is a fix to a long-standing cause of confusion and suffering. But it makes C# that bit more usable, so I’m going to mention it anyway.

Since C# 3, it’s been quicker and easier to write anonymous functions than named ones, thanks to lambda syntax. Anonymous functions are widely used in LINQ, but they’re also used in many other cases where you want to quickly parameterise behaviour without investing in some humungous hierarchy of classes and interfaces and virtual functions. An important feature of anonymous functions is that they can capture variables from their local environment. Here’s an example:

Here, i => i > n is an anonymous function that captures the value of n. For example, if n is 17, then the function is i => i > 17.

In previous versions of C#, if you wrote a loop, you couldn’t use the loop variable in a lambda. Actually, it was rather worse than that. You could use the loop variable in a lambda, but it would give you the wrong results — it would use the value of the loop variable at the time the loop was exited, not at the time the variable was captured.

For example, here’s a function which returns a collection of ‘adder’ functions, one ‘adder’ for each addend in the input:

Clearly this is horribly wrong! Every function in the returned collection has ended up capturing 5 as its addend. This is because they closed over the loop variable, addend, and the final value of the loop variable was 5.

To make this work in C# 3 and 4, you have to remember to copy the loop variable into a local variable (within the scope of the loop), and have your lambda close over the local variable:

Because the functions are closing over a local variable rather than the loop variable, the value is now preserved and you get the correct results.

This isn’t an obscure edge case by the way — I’ve come up against it numerous times in my projects. A more realistic example from one project is building a function to perform filtering. The function is built up from a collection of Restriction objects specified by the user. The code loops over the Restriction objects and builds up a list of functions representing the clauses (e.g. Name Equals “BOB” becomes r => r["Name"] == "BOB"), then combines these functions into a final filter function which runs all of the clauses and checks they are all true. My first pass at this didn’t work because each clause function ended up closing over the same Restriction object — the last one in the collection.

In C# 5, this is fixed and you can close over loop variables and get the results you expect. If you like to take advantage of C#’s hybrid OO-functional nature, this removes a nasty bear trap that has been causing problems for years.

So that’s it for C# 5. From a language point of view, there’s not a whole lot of new stuff to learn, though the async and await keywords conceal a great deal of depth. Happy coding!

[…] What else is new in C# 5? – Ivan Towlson discusses two of the other significant changes in C#5, looking at the new method caller information functionality which allows you to easily access details of the calling method, and also looks at a change to how loop variables are captured by lambda expressions, removing a common source of bugs. […]

Dear Microsoft, Just keep throwing features and more syntax in there. Soon we’ll be at C++ again and code that looks like worse line noise than Perl. Brilliant!

JeffMar 20th, 2012

That’s great, now I can use loop vars. BUT! My biggest consideration is why MS issued this cr@p at all? Didn’t they know that vars can be from cycles? It was a Perl motto: “it works as you see/expect”. MS decided “let these morons step on rakes, we warned in docs!” instead of preventing these stupid errors.
It seems MS’ architectors down from hindu trees, taking no care of their “conceptions”.

VincentMar 20th, 2012

Short & sweet article but the reading experience was utterly ruined by the floating social media tool bar. Please could you put it somewhere else?

I even created an interface that I use instead of actions to force users of my libraries to create entire classes instead of using the unnamed delegates, as they were getting a lot of errors related to the for variables, but were complaining that was an error of my library.
Now I can create the version that support actions again.

I agree about the tweet share bar to the point i did not finish the article

rcroederMar 20th, 2012

@capslock It is in dutch :P
@WTF suggestion: make your browser and/or resolution bigger. it’s not in the way anymore at 1360×768

ck06Mar 20th, 2012

The social media bar is a serious beating. I spread the browser over two screens to get enough room to read the article.

Whisky Tango FoxtrotMar 20th, 2012

Thanks. Useful article.

serg.fMar 20th, 2012

@Mudasir: No, C# generic type inference will figure out the generic type, so it’s safe to write plain Set(ref _f, v). If _f and v are ints then C# will figure out that T must be int, and fill it in automatically.

Ivan TowlsonMar 20th, 2012

@john: I think that would depend on how your aspect weaver was implemented. I would expect that the caller info attributes would not be that useful in AOP/attribute-based logging because the weaver would be inserting that information anyway.

Great!
The overloading was sold as something superior to optional parameters when MS switched us from VB6 to C#.NET. Now, ten yeas later, we are sold optional parameters as solution superior to overloading!
How much do they pay to promote that? May be I need to apply for that job?

NickMar 20th, 2012

@Nick, I don’t think Microsoft tried to sell anyone on overloading and not optional parameters, or even the other way around. I don’t think they had time to add everything in that users may or may not want. Anyway Microsoft didn’t switch you from VB6 to C#, they made VB.net for you, and it had syntax for optional parameters in 2003 at least right?

xer21Mar 20th, 2012

Sorry about the social buttons everyone. I’ve changed it so the buttons are integrated into the post for now so you should be able to read without a problem.

Excellent. I really like the INPC code – I’ll be using that for sure, and now you can close over loop variables I look forward to not declaring a local variable when I am using lambdas inside a loop (very common for me too!)

I don’t think it’s exactly accurate to say that you couldn’t use a loop variable in a lambda, you could and it would work perfectly well provided you understood what was happening and when.

The value is captured when the lambda is executed, not when it’s defined. There are times when the behaviour is useful. You can define a query once, closing over a local variable, then on each iteration of a loop alter the variable and execute the query getting different results without having to redefine the query every time.

It’s a useful, if not obvious, behaviour. I think it’s good that they’ve changed it to something more obvious as it’s one less place where deferred execution can trip you up, but I don’t think it’s right to dismiss the original functionality simply as wrong.

DaveMar 21st, 2012

@Dave: And that useful behaviour won’t change, because that is closing over a local variable which is then *used* within the loop. All that’s changing is the surprising behaviour of creating a closure *within the loop* over the *loop variable* itself, i.e. the range variable of a loop statement (e.g. the x in a foreach (x in…)). Locals that are declared and closed over outside the loop, then modified within with loop, retain the old behaviour.

And the change remains consistent with the behaviour you describe: the change is that for closure purposes loop variables are considered local to each iteration of the loop (like variables declared in the loop body) rather than local to the method that contains the loop. If they had changed the behaviour of locals, I would completely agree with you; but since they are only changing the behaviour of loop range variables, I’ll stand by describing the original functionality as wrong, because the result — multiple closures each using the final value of the loop variable — was not useful, and was never what anyone actually intended when they created a closure within a loop.

Hope this makes more sense now, and sorry if the original post was not clear about what was changing!