My First C# 3.0 Program

March 23, 2007

no comments

I’ve finally decided to download the new "Orcas" CTP of Visual Studio, which includes support for the all new C# 3.0. Up until now I only read about it, so I thought it was about time I tried it myself. And it’s awesome.

So, here’s my "hello world" program.

public void MyFirstProgram(Func<string,string> doSomethingWithString)
var result
= doSomethingWithString("dlroW olleH");

public void Main()
=> new string(str.Reverse().ToArray()));

This useless program demonstrates a few of the new C# 3.0 features.

The first thing you can notice about MyFirstProgram method, is the use of the "var" keyword. Is this javascript or C#? What’s going on? Well, don’t worry. C# has not gone all dynamically-typed on us. It’s still very much statically typed, but it includes a new feature which allows us to specify local variables (and local variables only) without specifying their types. The compiler infers the type from by looking at the initializer for it. So this won’t compile, since the compiler won’t know how to infer the variable type:

var noInit;

Neither will this compile:

var x = 5;
= "5";

Remember, this is not javascript. Once the compiler has decided about the type of the local variable, it can’t be changed again.

The second weird thing you’ve probably noticed is this weird syntax: "str => …". This is actually an easier way to create an anonymous delegate. It’s definitely easier than what you had to write in C# 2.0, which is…

delegate(string str)
return new string(str.Reverse().ToArray();

So str is the delegate parameter, but as you can see, we don’t have to specify its type. The compiler infers the type of the parameter using the method to which we pass the delegate. In our case, it’s this:

public void MyFirstProgram(Func<string,string> doSomethingWithString)

Func is a new built in generic delegate type, which has a few overloads. We’re using the one in which we have one return value and one parameter, and our generic type is string. So, this method actually accepts a method, whose both return value and single parameter are strings. The cool thing is, that even though the "str => …" does not specify the type of str, there is intellisense support for it in the new Visual Studio. So not only the compiler got a lot smarter in C# 3.0 – Visual Studio followed suit.

I really like the step the language has taken towards functional programming. The lambda expressions ("=>" syntax) really remind me of the Lisp variants of programming languages, and I can’t wait to do more cool stuff with it. Still, the whole thing probably wouldn’t have worked without great intellisense.

The next thing you might notice, is that String doesn’t have a Reverse() method. You might think that in the new .NET Framework 3.5 the String class has changed, but as far as I can tell, it’s exactly the same as in .NET 2.0. So where did this "Reverse" came from?

Well, another new feature of C# 3.0, and an integral part of the Linq project, is extension methods. This feature allows you to extend classes that you can’t or don’t want to inherit from. This includes built in .NET types as string, int, or in our case – the IEnumerable<T> interface. So Reverse is not a String method, what it really is, is an extension to the IEnumerable<T> interface. Since string implements IEnumerable<char>, it gets, "for free" a whole bunch of new methods which you can use. That means that if you’re writing a collection, you don’t have to inherit from some base-class to get lots of useful methods, if you only implement IEnumerable<T> you’ll get methods like Reverse, Sum, Average, and many more.

To see how this works, let’s "go to definition" on our reverse method. We’ll see this:

namespace System.Linq

public static class Enumerable
public static IEnumerable<TSource> Reverse<TSource>(this IEnumerable<TSource> source);

As you can see, we were sent to the static Enumerable class with a lots of static methods, which include parameters such as "this IEnumerable<TSource>". This is the syntax for creating an extension to a certain class.

Let’s have a look at the Reflector to better understand what’s going on (I actually had to go and use an older version of the Reflector to show you what’s under. The new Reflector got all smart on me and displays the code almost identically as its C# origin).

1 [CompilerGenerated]
2 private static Func<string, string> <>9__CachedAnonymousMethodDelegate1;
4 public void MyFirstProgram(Func<string, string> doSomethingWithString)
5 {
6 string text1 = doSomethingWithString("dlroW olleH");
7 Console.WriteLine(text1);
8 }
9 10 public void Main()
11 {
12 if (Class1.<>9__CachedAnonymousMethodDelegate1 == null)
13 {
14 Class1.<>9__CachedAnonymousMethodDelegate1 = new Func<string, string>(Class1.<Main>b__0);
15 }
16 this.MyFirstProgram(Class1.<>9__CachedAnonymousMethodDelegate1);
17 }
18 19 [CompilerGenerated]
20 private static string <Main>b__0(string str)
21 {
22 return new string(Enumerable.ToArray<char>(Enumerable.Reverse<char>(str)));
23 }

For the purpose of this post, I will ignore the way the compiler handles anonymous delegates (the reason for the CachedAnonymousDelegate1 thingy and the auto-generated b_0 method).

First look at line 6: the "var" keyword is gone, and all you see is a declaration of a string local variables.

Now look at line 22: Our "Reverse" method shows its true form… A call to the Enumerable.Reverse static method.

In fact, as you can tell, there’s no new CLR coming with Orcas. All these new features are strictly compilation features, so only the C# compiler got smarter – the underlying CLR is still at version 2.0.

For more information about extension methods, check out ScottGu’s post.

Anyway, I intend to dig in some more in C# 3.0 – especially in Linq, which I have yet to really explore. So more on that later.

Add comment
facebook linkedin twitter email

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>