Sunday, November 26, 2006


New Features in C# 3.0 (part 2)

Implicitly Typed Local Variables

Implicit typing of local variables is a language feature that allows the type of a variable to be inferred at compile time from the type of the variable’s initialization expression. LINQ query expressions can return types, created dynamically by the compiler, containing data resulting from queries.

var n = 3;

var s = "Twas brillig";

var d = 3.141592653;

var digits = new int[] { 1, 2, 3, 4, 5 };

Declaring Implicitly Typed Collections

Implicitly typed variables are useful when instantiating complex generic types:

var supplierProducts = new Dictionary<string, List<string>>();

var products = new List<string>();




supplierProducts.Add("grocer", products);

products = new List<string>();




supplierProducts.Add("butcher", products);

int totalProducts = supplierProducts["grocer"].Count +


Console.WriteLine("Total products: {0}", totalProducts);

Implicitly typed variables should not be confused with untyped variables in scripting languages such as VBscript, or variants in VB6, where a variable can hold values of different types over the course of its lifetime. Once the compiler infers an implicit variable’s type from the expression used to initialize it, it’s type is then fixed just as if the variable had been explicitly declared with that type. Assigning a value of a different type will result in a compile time error.

var x; // Error: type is not known.

var x = { 1, 2, 3 }; // Error: type is not known.

var n = 8; // n implicitly typed as int

n = "This will not compile";

Extending Types with Extension Methods

Extension methods enable developers to extend the functionality of existing types by defining new methods that are invoked using the usual instance method syntax. Extension methods (defined as static) are declared by specifying the modifier keyword this on the first parameter of the method. Extension methods can be added to any type, including the generic types such as List and Dictionary, as shown in this slightly contrived example:

public static class Extensions


public static Dictionary<K, T> Combine<K, T>(this Dictionary<K, T> s Dictionary<K, T> d)


var newDictionary = new Dictionary<K, T>(s);

foreach (K key in d.Keys)


if (!newDictionary.ContainsKey(key))


newDictionary.Add(key, d[key]);



return newDictionary;



Initialise two dictionaries and then combine them using the extension method just defined:

var supplierProducts = new Dictionary<string, List<string>>();

products = new List<string>();




supplierProducts.Add("butcher", products);

var supplierProducts2 = new Dictionary<string, List<string>>();

products = new List<string>();




supplierProducts2.Add("butcher", products);

var x = supplierProducts.Combine<string, List<string>>(supplierProducts2);

Lambda Expressions

C# 2.0 introduced anonymous methods, which allow code blocks to be “inlined” where delegate values are expected. For example, the List FindAll method requires a delegate parameter:

List<int> oddNumbers = list.FindAll(delegate(int i) { return (i%2) != 0; }

Here, the delegate determines whether the input integer is an odd number. C# 3.0 takes this further and introduces lambda expressions, a functional programming syntax for writing anonymous methods.

A lambda expression is written as a parameter list, followed by =>, followed by an expression. The parameters of a lambda expression can be explicitly or implicitly typed. In an explicitly typed parameter list, the type of each parameter is explicitly stated:

(int x) => x + 1

In an implicitly typed parameter list, the types of the parameters are inferred from the context in which the lambda expression is used. In addition, if a lambda expression has a single, implicitly typed parameter, the parentheses may be omitted from the parameter list:

x => x + 1
(x,y) => return x * x + y * y

Here is an example of using a single variable lambda expression:

var list = new List<string>();







var matchStartsWithCA = list.FindAll( s => s.StartsWith("ca") );

foreach (string matchString in matchStartsWithCA)




Hands-On Lab: Lab Manual: C# 3.0 Language Enhancements


Powered by Blogger