C# in Depth: Chapters 6 and 7 now in MEAP

Chapters 6 and 7 have now been included in the Manning Early Access Program. That means that the whole of the C# 2 part of the book is now available. Marc Gravell has been picking holes in it on the forum (and I mean that in a very positive way – it’s great to have more eyes running over it). Can you find more errors? Here’s a rundown of chapters 6 and 7:

 

Chapter 6: Implementing iterators the easy way

In C# 1, it was a pain to implement IEnumerable. C# 2 makes it easy with iterator blocks, and this can make it worthwhile introducing IEnumerable where you might not have done before. Aside from anything else, it’s fun just to watch the C# compiler build a state machine for you!

 

Chapter 7: Concluding C# 2: the final features

Confession: this is really “C# 2: the features which didn’t fit anywhere else”. It’s a round-up of features which didn’t deserve their own chapters, and which could easily wait until the “big” features had been explored before being mentioned. Ironically, C# 3 is exactly the opposite – the “little features” in C# 3 are pretty key to understanding the big features such as lambda expressions and query expressions, which is why they’re in chapter 8. Chapter 7 covers the following areas:

  • Partial types (including partial methods from C# 3)
  • Static classes
  • Separate getter/setter property access (e.g. public getter, private setter)
  • Namespace aliases (using ::, the global namespace alias, and extern aliases)
  • Pragma directives
  • Fixed size buffers

Fun with captured variables

 

I’m currently writing about readability, and discussing deferred parameter evaluation in LINQ on the C# newsgroup. It’s led me to come up with quite an evil application of captured variables.

Consider this C# 3 code:

using System;
using System.Linq;

public class Test
{
static void Main()
{
int max = int.MinValue;

int[] values = { 0, 5, 2, 3, 8, 4, -1, 10, 12, 8, 100 };

var query = from value in values
where value > max
select (max=value);

foreach (int value in query)
{
Console.WriteLine(value);
}
}
}

The max and values variables are easy enough to understand, and the foreach loop at the bottom just iterates through the query and dumps out the results – but what does the query itself do?

The answer is that it shows you all the values which are larger than any that have come before it. Each value encounters the “where” clause which is effectively “are you the biggest value I’ve seen so far?” and passing values then encounter the “select” clause which is “remember the current value as the highest we’ve seen, and return it”. So, the output is 0, 5, 8, 10, 12, 100.

It relies on the fact that the “select” clause for one passing value is executed before the next “where” clause. If you force it to evaluate the “where” clause for all the source values before performing the projection (e.g. with an “orderby” clause) then all the numbers are returned, because they’re all bigger than the initial value of max. If you try to use Parallel LINQ to evaluate it, all bets are off.

 Contrary to the normal advice, do try this at home. Just don’t try it in production code. (If you find a genuine use for it, at least comment it heavily!)

LINQ to Silliness: Generating a Mandelbrot with parallel potential

I’ve been writing about LINQ recently, and in particular I’ve written a small amount about Parallel LINQ. (Don’t get excited – it’s only about a page, just to mention it as a sort of “meta-provider” for LINQ.) I was wondering what to use to demonstrate it – what general task can we perform which could take a lot of CPU?

Well, I used to be quite into fractals, and I’ve written Mandelbrot set generators in various languages. I hadn’t done it in C# before now, however. Calculating the colour of each pixel is completely independent of all the other pixels – it’s an “embarrassingly parallelizable” task. So, a great task for PLINQ. Here’s the “normal LINQ” code:

 

var query = from row in Enumerable.Range(0, ImageHeight)
from col in Enumerable.Range(0, ImageWidth)
select ComputeMandelbrotIndex(row, col);

byte[] data = query.ToArray();

Changing this into a parallel query is really simple – although we do need to preserve the ordering of the results:

var query = from row in Enumerable.Range(0, ImageHeight).AsParallel(QueryOptions.PreserveOrdering)
from col in Enumerable.Range(0, ImageWidth)
select ComputeMandelbrotIndex(row, col);

byte[] data = query.ToArray();

Without being able to actually use PLINQ yet, I can’t tell how awful the order preservation is – Joe warns that it’s costly, but we’ll see. This is on a pretty giant sequence of data, of course… An alternative would be to parallelize a row at a time, but that loses some of the purity of the solution. This is a very, very silly way of parallelizing the task, but it’s got a certain quirky appeal.

Of course, there’s then the code for ComputeMandelBrotIndex and displaying a bitmap from it – the full code is available for download (it’s a single C# file – just compile and run). Enjoy.

Update!

This blog post has been picked up by Nick Palladinos, who has written his own Parallel LINQ provider (much kudos for that – unfortunately for me the blog is in Greek, which I don’t understand). Apparently on a dual core processor the parallelised version of the Mandelbrot generator is indeed about twice as fast – it works! Unfortunately I can’t tell as my laptop only has a single core… it’s very exciting though :)

Yeehaa! Framework source code, here we come!

It’s just been announced on Scott Guthrie’s blog that Visual Studio 2008 will allow debugging into the source code for the .NET framework – at least for some areas. I’ve wanted this to happen for a long time, and blogged about it before now – but I didn’t honestly expect it to happen, at least not for a long time.

This is a fabulous move, and one which MS should be commended for. I’m sure many people will spend a long time discussing whether the licence can be described as “open” (you can’t copy the code or recompile it) but to me that’s relatively unimportant. I will be able to view it, debug into it, and potentially spot/report bugs in it. I don’t really have much use for copying or recompiling it, personally.

Well done, Microsoft.

On a side note, I’d love to see the traffic logs for Reflector before and after this happens :)