Marek Safar's (b)log

Wednesday, 9 December 2009

I am very happy to announce that the Mono C# compiler is now C# 4.0 feature complete.

Covariance and contravariance

The initial work was done by Scott Peterson and then I take taken over and continue developing and advancing the feature. The implementation was rather straightforward especially because C# 4.0 only supports covariance and contravariance on delegates and interfaces. The trickiest and most challenging part was to upgrade type inference to deal with variant type arguments and to provide a meaningful error reporting.

Optional parameters

Optional parameters as of C# 4.0 are limited to the CLR 2.0 functionality which in plain speak essentially means that only constant expressions are supported. The feature adds what VB supported for quite some time but does not add anything new although the integration with existing features like nullable types has been done.

Named arguments

This is probably the trickiest new features of C# 4.0. It may look like simple add-on but by its nature it relates to the most complicated part of C# language. There were several areas where we had to be careful such us overload mechanism, side effects execution, virtual methods, and partial method integration. Most importantly to ensure left to right evaluation any non-constant expression is always copied before next argument is evaluated. This could have a small performance penalty but it was necessary to make our implementation robust.

Dynamic binding

I am not going to explain what dynamic binding is as many people did it before and it can be easily found on the Internet. Instead I am going to focus on how we have implemented it and where it fits to Mono stack.

Dynamic binding is fully integrated into the C# language and any statically bound expression can also be bound dynamically using the new “dynamic” type. This may sound easy but it has been a lot of work even if we had sources of Dynamic Language Runtime (DLR) available when started it and Mono C# compiler has been written in C# from the begging. To better illustrate the concept from compiler perspective here is the structure we ended up with.

Static compilation is on the left side, we can call it a phase I, where everything goes as usual until keyword “dynamic” is resolved in C# source file. At this point all what can be done is to pack the expression and its context into what is usually called payload and redirect the resolver to this payload which gets later emitted instead of evaluated expression. At this point I'd like to point out that even if C# compiler defers the actual resolution to runtime it still tries to do as many static checks as possible to reduce number of possible errors from dynamic binder.

Now we have successfully compiled our application and we can run it. Any dynamic binding code can only run on Mono trunk or .NET 4.0 as it requires a new dynamic binder infrastructure which had not been available in versions before. What you can see on the right side of the image is the magic box called DLR which is the dynamic infrastructure handling all dynamic operations on top of CLR and that's where we come back to life with our dynamic C# binder. We defer all dynamic handling to DLR and only register our payload with DLR call-site so we can be called when DLR decides there is a need for dynamic resolution. When such situations happens C# runtime binder loads the payload created in the phase I and calls back the Mono C# compiler resolver with the restored expression and the context mimicking the static compilation. This has huge benefits for Mono as we have a single code base for both static and dynamic binder. It also has a positive impact on dynamic binder as errors reported during runtime execution will be exactly same as with static binder.

It's also worth mentioning that DLR works strictly with objects only which means any value types dynamic operation will require numerous boxing and unboxing operations and that will slow it down the operation significantly and should be therefore considered before using with dynamic binder.

What about other C# 4.0 features?

There is not really that much left. We have decided not to implement true COM interoperability features for now as we see a minimal usage for them in Mono stack however we may reconsider it at a later stage.

Thursday, 24 July 2008

I am pleased to announce that Mono C# compiler (gmcs) has now full C# 3.0 support. Most of the features has been available since Mono 1.2.6 release. However, with the upcoming Mono 2.0 release we will also support complex LINQ expressions and mainly expression trees which is fairly overlooked new feature with a lot of potential.

For anyone interested in compiling and running this LukeH's slightly extreme LINQ example I have good news. It compiles on Mono and it runs as fast as on .NET.

Friday, 22 June 2007

We are working on full C# 3.0 support for the Mono gmcs compiler and today I am pleased to announce full support of implicitly typed local variables and implicitly typed arrays.

Implicitly typed local variables

Those who have never heard about implicitly typed local variables maybe noticed new C# 3.0 keyword called `var'. However, the var is not a real keyword; it is what I would call transparent keyword. It behaves like keyword but only if there is no collision with a type of the same name. The rationale behind this is obvious, to make migration to new version as smooth as possible. Therefore, if your existing code uses type called var, don't worry, it will still compile in the same way as it did with the previous version of C# compilers.

As the name says one can use var to implicitly type local variable as shows the following example.

Everywhere var keyword is used, the compiler tries to infer the variable type based on a type of variable initializer. This limits implicitly typed local variables to be used only in a local variable declaration, for each, for, or using statements.Also as the name says, implicitly typed local variable, you cannot use var for field declaration or constant variables, therefore following declarations will both produce a compiler error.

Interesting, C#, statically typed language and I cannot see any type whatsoever. How does it work then? It is not that hard to guess, as many other new C# 3.0 features also this one uses type inference. So, if it is possible the compiler tries to infer an array type based on common type (implicit conversion has to exist) of all elements in the array initializer otherwise a compiler error is issued and you have to specify type explicitly. The current draft of C# specification does not mention anything about implicitly typed multi-dimensional arrays. However, the latest Microsoft compiler supports implicitly typed multi-dimensional arrays with the syntax similar to an explicitly typed array. Although they are supported, hard to say whether it is a bug or a feature with required comma syntax.

Thursday, 15 February 2007

Mono compiler gets the full support of extension methods, the first C# 3.0 feature. A patch which adds extension methods support to gmcs just landed on SVN. Let’s look at some interesting details.

Extension methods are static methods that can be invoked using instance method syntax. In effect, extension methods make it possible to extend existing types and constructed types with additional methods. -- C# 3.0 Specification

Sounds good, so how can I make my method extension method?

A method became the extension method when the first method parameter contains `this’ modifier. Extension methods can be declared in non-generic top-level static classes which mean that extension methods can be declared as static only. There are further limitations but they only covering corner cases. For those interested, I recommend browsing Mono compiler test suite to get some ideas.

Note: If you want to use extension methods you need to pass `langversion:linq’ option to compiler to unlock C# 3.0 specific features; although extension methods are included in gmcs compiler.

When you try to compile the sample, it will compile successfully and an instance method call will be converted to a static method call by compiler. How is it possible? The method `Prefix’ is the extension method of `string’ class and no other method with same parameters exists and therefore the method is selected as the best overload candidate.

Wishing to use extension methods in more advanced scenario, things become little bit more complicated and you have to use `using ’ to import your extension methods from different namespace or an assembly.

Confusing, isn’t it? Well, not that much. Extension methods are included in method resolving process if standard (non-extension) process failed to find a match. The compiler will look for extension methods in the current namespace context and if no suitable method was found, the process will continue inspecting all referenced namespaces in the current namespace. In the case of method was not found, the compiler continues in parent namespace until either method is found or parent namespace does not exist.

My overall feeling about the feature is mixed as extension methods clearly reduce code readability. Fortunately, I was pleased to read the recommendation "to use extension methods sparingly and only if it is not possible to use instance methods" directly inside C# Standard.