One of the sessions we were very fortunate to have presented to us at the ASPInsiders Summit was Anders Hejlsberg on C# and Linq. We finally let him go after nearly 3 hours and everyone was pretty ecstatic about this session and the fact that Anders was so generous with his time.
It was interesting to see how the language innovations in C# combine to enable Linq, yet individually, they are all very powerful. One of the goals he told us of C# 3 was to find more expressive ways of programming, increase conciseness and up the level of abstraction. He told us that after the first 2 phases of C# (1.x and 2.0), they were "kind of done with what we can do with OO programming".
Most of what he showed us for C#3 has a correlation in VB9 which enables both languages to achieve the Linq functionality. Interestingly, we saw Iron Python towards the end of our three days, and I can see how what Anders showed us in C#3 has a lot in common with dynamic languages. It was also interesting to see C# tolerant of coding in a less-strongly typed manner. Something that C# folks have jabbed VB devs about for years.
I'm sure I'd get razzed by the VB team if I only talked about C# here, so I will talk about both. This is not an exhaustive list of the new things in the languages, just a few to whet your appetite.
So, although all of these tools are leveraged in Linq, they are not solely for Linq. You can use them anywhere in .NET. In fact, I'm not using any Linq examples below.
Note that you can find much more detail in the MSDN articles "Overview of Visual Basic 9.0" and "C# 3.0 Specification". I will cover a few of them. But the key is to remember that all of these come together to make Linq work.
Implicitly Typed Local Variables (C#3 & VB9)
C#3: var i=5; | var numbers = new int[] {1,2,3};
VB9: Dim i=5 | Dim numbers = New Integer() {1,2,3)
Don't confuse "var" with the "var" in javascript.
The statement is basically saying that "i is the type on the right". The language can already tell that 5 is an integer, so why state the obvious? :-) One benefit is that the coding is a little simpler, especially when dealing with more complex types. But more importantly, this saves you when you get into the situation where you just can't describe the type (not an uncommon scenario in Linq) or just don't really need to because it is something you are using in passing.
.Anonymous Types
Anonymous Types take the implicitly typed variables one step further, where "the thing on the right" is a type but you don't have to declare or define it in advance. The language just figures it out and we don't have to define, declare or even come up with a name to call the new thing we are creating.
C#
var thingamajig = new { Name = "Lawnmower", Price = 495.00 };
VB
Dim thingamajiggy= New { .Name="Sprinkler", .Price=18.00}
Object & Collection Initializers
Object initializers let you create instances of structure classes on the fly. You can initialize the fields & values all in one statement without having to define the structure in advance.
C#
var a = new point {x=0; y=1}
VB
Dim a = new point {x=0, y=1}
instead of having to define the point structure in advance. the examples also you implicit variables.
You can also create new objects based on classes on the fly, If you had a class "Country" with members "Name" and "Population", you could write
C#
var c=new Country {
Name="Canada",
Population=32800000 }
VB
Dim c = New Country { .Name="U.S.", .Population=300000000}
And, using this concept, you can create collections really easily in both languages.
Extension Methods
Talk about flexibility! Extension methods let you extend an existing type with new methods. Anders referred to this as a compile time illusion. The method is created with a pointer back to whatever type calls it and can be performed on any type that matches its signature.
A simple example would be a method that will Count the # of occurrences of the letter A in any string passed in.
public static void Print(this object obj) //note that I have included "this" in the parameters
{
Console.WriteLine(obj);
}
VB
Public Shared Sub Print ([Me] obj as Object)
Console.WriteLine(obj)
End
Now you can write
123.Print();
"hello world".Print();
You can combine extension methods as well. If we had another called CountProperties, we could write:
mystring.Print.CountProperties
Where Linq leverages this is that you can have the signature call for an IEnumerable(Of T)/<T> and then attach it to any Linq query, since they all return an IEnumerable.
There's more more more
Anders also went over Lambda expressions and then dove deep into Linq. But this blog post is long enough and I'll save it for another time. ;-)