July 30, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

A Preview of What's New in C# 3.0

  • November 4, 2005
  • By Sahil Malik
  • Send Email »
  • More Articles »

Lambda Expressions: The Espresso of Anonymous Methods

C# 1.x allowed you to write code blocks in methods, which you could invoke easily using delegates. Delegates are definitely useful, and they are used throughout the framework, but in many instances you had to declare a method or a class just to use one. Thus, to give you an easier and more concise way of writing code, C# 2.0 allowed you to replace standard calls to delegates with anonymous methods. The following code may have been written in .NET 1.1 or earlier:

class Program
{
   delegate void DemoDelegate();
   static void Main(string[] args)
   {
      DemoDelegate myDelegate = new DemoDelegate(SayHi);
      myDelegate(); 
   }
   void SayHi()
   {
      Console.Writeline("Hiya!!") ;
   }
}

In C# 2.0, using anonymous methods, you could rewrite the code as follows:

class Program
{
   delegate void DemoDelegate();
   static void Main(string[] args)
   {
      DemoDelegate myDelegate = delegate()
         {
            Console.Writeline("Hiya!!");
         };
      myDelegate();
   }
}

Whereas anonymous methods are a step above method-based delegate invocation, lambda expressions allow you to write anonymous methods in a more concise, functional syntax.

You can write a lambda expression as a parameter list, followed by the => token, followed by an expression or statement block. The above code can now be replaced with the following code:

class Program
{
   delegate void DemoDelegate();
   static void Main(string[] args)
   {
      DemoDelegate myDelegate = () => Console.WriteLine("Hiya!!") ;
      myDelegate();
   }
}

Although Lambda expressions may appear to be simply a more concise way of writing anonymous methods, in reality they also are a functional superset of anonymous methods. Specifically, Lambda expressions offer the following additional functionality:

  • They permit parameter types to be inferred. Anonymous methods will require you to explicitly state each and every type.
  • They can hold either query expressions (described in the following section) or C# statements.
  • They can be treated as data using expression trees (described later). This cannot be done using Anonymous methods.

Query Expressions

Even though further enhancements may be introduced in the coming months as C# 3.0 matures, the new features described in the preceding sections make it a lot easier to work with data inside C# in general. This feature, also known as LINQ (Language Integrated Query), allows you to write SQL-like syntax in C#.

For instance, you may have a class that describes your data as follows:

public class CoOrdinate
{
   public int x ;
   public int y;
}

You now could easily declare the logical equivalent of a database table inside C# as follows:

// Use Object and collection initializers
List<CoOrdinate> coords = ... ;

And now that you have your data as a collection that implements IEnumerable<T>, you easily can query this data as follows:

var filteredCoords =
   from c in coords
   where x == 1
   select (c.x, c.y)

In the SQL-like syntax above, "from", "where", and "select" are query expressions that take advantage of C# 3.0 features such as anonymous types, extension methods, implicit typed local variables, and so forth. This way, you can leverage SQL-like syntax and work with disconnected data easily.

Each query expression is actually translated into a C#-like invocation behind the scenes. For instance, the following:

where x == 1

Translates to this:

coords.where(c => c.x == 1)

As you can see, the above looks an awful lot like a lambda expression and extension method. C# 3.0 has many other query expressions and rules that surround them.

Expression Trees

C# 3.0 includes a new type that allows expressions to be treated as data at runtime. This type, System.Expressions.Expression<T>, is simply an in-memory representation of a lambda expression. The end result is that your code can modify and inspect lambda expressions at runtime.

The following is an example of an expression tree:

Expression<DemoDelegate> filter = () => Console.WriteLine("Hiya!!") ;

With the above expression tree setup, you easily can inspect the contents of the tree by using various properties on the filter variable.

One to Grow On

C# 3.0 offers incredible new features that make your work as an application developer and architect a lot easier, and yet it remains a programming language that lends itself to stricter and cleaner architecture.

C# 3.0 is in its infancy right now and it will mature in the coming months, but given the sizable impact its changes will have on the surrounding .NET Framework, its recommended architecture, and design patterns, definitely keep your eye on it.

About the Author

Sahil Malik has worked for a number of top-notch clients in Microsoft technologies ranging from DOS to .NET. He is the author of Pro ADO.NET 2.0 and co-author of Pro ADO.NET with VB.NET 1.1. Sahil is currently also working on a multimedia series on ADO.NET 2.0 for Keystone Learning. For his community involvement, contributions, and speaking, he has also been awarded the Microsoft MVP award.





Page 2 of 2



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel