Wednesday, 21 July 2010

Lambda, delegate, anonymous & implicit goodness in C#

Spent last night reading up on some of the finer points of C# in Jon Skeet’s excellent book C# in depth (http://manning.com/skeet/)

I have introduced some of the newly learned syntaxes into my DSL parser. I have included a step by step explanation of some of these syntaxes that may appear alien to a .NET 2.0 developer.

I created an inline delegate function to be used within my tokeniser function to determine if a string character was a double or single quote as follows:-

Func<string,bool> IsQuote = a=>(new [] {"\"","'"}).Contains(a);

...and called within the same function...

if (IsQuote(c)){//do something}

Breaking this down into it’s constituent parts we have

Part 1

Func<string,bool> IsQuote = a=>(new [] {"\"","'"}).Contains(a);

Declare (a pointer to) a function that accepts a string parameter and returns a bool. This uses the Func<T,U> type, the last generic always representing the return type.

Part 2

Func<string,bool> IsQuote = a=>(new [] {"\"","'"}).Contains(a);

Assign the function definition to this function pointer.

“a” is an implicit (string) type as it represents the first parameter in the function so the string declaration can be dropped

“a=>” is shorthand for delegate (string a){...}

A more verbose version might look like this…

Func<string, bool> IsQuoteAlso;

IsQuoteAlso = delegate(string a) { return a == "\"" || a == "'"; };

 Part 3

Func<string,bool> IsQuote = a=>(new [] {"\"","'"}).Contains(a);

Create a new array of strings using an implicit declaration (the compiler figures out that this is a new array of strings) and then call the contains method.

The next question is, will these syntaxes become part of everyday development; will a “regular” developer be able to work with these new shortcuts. Time will tell.

Jon.

Thursday, 8 July 2010

StringBuilder & Reflection performance myths?

Following feedback from recent system testing I looked into a performance issue in my .NET based DSL interpreter. The interpreter coverts the travel industry DSL into .NET CLR calls through reflection.

I started by creating a unit test which performed a where clause on the result of a where clause where the target list was 1000 records.

The DSL looked something like this

@result=Itinerary.Notes.Where(Value Contains “Hello”).Where(Value EndsWith “World”)

This chained approach resulted 2000 iterations and took 5 seconds to execute.

I assumed that reflection was the problem so I reran my performance unit test after adding caching to my ExpressionTree. I was surprised to learn that the improvement was negligible (from 5.1 seconds to 5 seconds). The intention was to reduce the number of reflection calls based upon “common wisdom” that reflection is slow.

I then ran the VS2008 Performance Explorer/Wizard over the interpreter and spotted that a derived String.Concat method was using up the majority of working memory at runtime. I fixed this in the heaviest used method which tokenises the script before passing it to the expression parser (replacing a simple activeToken += currentChar style approach with a StringBuilder.Append(currentChar) approach).

There were some interesting results...the following unit test demonstrates how a pre-initialised string builder can introduce a MASSIVE improvement in runtime speed. String concatenation is extremely slow, the string builder extremely fast and the reflection calls (contrary to common wisdom) are in fact really fast.

image

Results:

00:00:16.2104000
00:00:00
00:00:00.0780000

Monday, 18 January 2010

XAML Editor Missing in VS2008 64bit with Windows 7

I'm not sure if this a 64 bit problem, a Windows 7 problem or just a VS2008 SP1 problem but I have been pulling out the little hair that I have left trying to get the intellisense working for XAML files on my new install. At best, I could get the files to be opened up in the XML editor, but the WPF editor was missing.

Fortunately I found this post. There were plenty of partial solutions but strangely two solutions had to be combined

1. Run devenv /setup from the VS command prompt in admin mode
2. Follow this with devenv /resetskippkgs

Job done.