Showing posts with label Mono. Show all posts
Showing posts with label Mono. Show all posts

Wednesday, 9 December 2009

Mono and C# 4.0

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, 15 February 2007

C# 3.0 Extension Methods

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.
static class MyExtension
{
public static string Prefix (this string s, string prefix)
{
return prefix + s;
}
}

class M
{
public static void Main ()
{
string s = "abc".Prefix ("1");
}
}

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.