maandag 2 januari 2006

C# 3.0 Orcas : playing with LINQ

I’ve been playing around with the technology preview of C# 3.0 today. The most important new feature of C# 3.0 is –without any doubt - LINQ.

LINQ enables you to search through collections in an SQL – like way.

For instance, instead of looping through a collection to find the Persons that live in the city that has the postal-code ‘9000’ like this:

List<person> persons = new List<person>();

persons.Add (new Person("Person1", "9000"));
persons.Add (new Person("Person2", "9870"));
persons.Add (new Person("Person3", "9000"));

foreach( Person p in persons )
{
if( p.PostalCode == "9000" )
{
Console.WriteLine (p.Name);
}
}


You will be able to get the same results, by writing the code like this:

List<person> persons = new List<person>();

persons.Add (new Person("Person1", "9000"));
persons.Add (new Person("Person2", "9870"));
persons.Add (new Person("Person3", "9000"));

var result = from p in persons
where p.PostalCode == "9000"
select p.Name;

foreach( string name in result )
{
Console.WriteLine (name);
}


You can imagine that, for complex queries, using LINQ can be an advantage since it keeps your code more readable / understandable.

In order to be able to deliver this functionality, Microsoft had to add some other features to the language:

Implicit types


C# 3.0 introduces the var keyword. If you take a look at the LINQ code example, you’ll see that I’ve used this keyword.

With this keyword, you don’t have to declare the type of the variable. So, when I first saw this, I thought ‘Oh no, is this the same like the ‘variant’ type in VB, and is C# going ‘the VB way’ ?
Luckely, Microsoft has defined some ‘rules’:

  • When declaring a ‘var’, you’ll have to initialize the variable
  • You cannot initialize the variable to null.

So, these restrictions save us from the ‘variant’, because, because of these rules, the type of the variable is specified by the initializer.

The var keyword can be handy in some situations. For instance, suppose you want a Dictionary object like this:
Dictionary<CustomerKey, Customer> custs = new Dictionary<CustomerKey, Customer> ();


You’ll be able to write it in a shorter way like this:
var custs = new Dictionary<CustomerKey, Customer> ();

Extension Methods


Extension methods allow you to ‘extend’ the functionality of a class without the need to change (and recompile) that class, and, without the need to create a subclass of that class (which is not possible if the class that you want to inherit from, is sealed.

Suppose you want to extent the Person class I’ve used in the previous example using an extension method, you’ll have to do it like this:

public static class PersonExtension
{
public static string GetPostalCodeAndName( this Person p )
{
return p.PostalCode + " " + p.Name;
}
}


An extension method is a static method with at least one argument: The first argument of the extension method must be a variable of the type that you want to extend, and, it must be preceded by the this keyword.

The extension method can then be used like this:
Person p = new Person("Person1", "9000");

Console.WriteLine (p.GetPostalCodeAndName());


Luckely, you’re not able to access the non-public members of the class in the extension method.

Anonymous types and Initializers


These 2 features are also added to the c# specification in order to make LINQ possible. However, apart from that, I do not see why I’m going to use these 2 features, so I’m not going to discuss them here.
You’ll find more information about these features (and about the other new C# 3.0 features) on the MSDN

DLINQ


DLINQ is a MS research project that makes use of the LINQ technology. It allows the developer to query a database using similar statements like the ones you use with LINQ instead of using embedded SQL or calling stored procedures.

I haven’t played with DLINQ (yet), but anyway, I’m a little bit sceptical on it.
From what I’ve seen, you have to specify mapping information in your ‘domain object’, so that messes things a little bit up.
I also wonder how this will behave with a complex domain model; in applications with a complex domain model, the domain model is not a one-to-one mapping of the database.
Anyway, it’s an experimental project, and we’ll see what the future brings.

If you want to experiment with LINQ, you can get the technology preview here

Update:The C# code that used generics was not shown properly.

2 opmerkingen:

Dimitri zei


The var keyword can be handy in some situations.

Dictionary custs = new Dictionary ();

You’ll be able to write it in a shorter way like this:

var custs = new Dictionary ();


Is this the only advantage of the 'var'-type?
Writing var custs = ... instead of MyVeryLongTypeName custs = ... is not very important to me. It's just a few character less to type.
Is it, for example, possible to define another type to this variable. Like this:
var custs = new Dictionary();
custs = new LinkedList();

Frederik Gheysels zei


Is it, for example, possible to define another type to this variable. Like this:
var custs = new Dictionary();
custs = new LinkedList();


No, this is -luckely- not possible. The var keyword does not behave like the variant type in VB.
When you use the var keyword, you'll have to initialize your variable at declaration time.
So, the type of the variable is implicitly determined by the initializer. Once initialized, you cannot assign another type to it.
The var keyword was introduced because it was necessary for LINQ.
For more information, I'll refer you to the blog of Dan Fernandez. He has an article in where he explains the purpose of var.