C# in Depth

Cover of C# in Depth
Order now (3rd edition)

Bluffer's Guide to C# 3

Obviously C# in Depth teaches the new features of C# 3 in depth. However, if you want to bluff it for the moment (just until your copy of the book arrives, of course) - welcome to the bluffer's guide. This isn't intended to give you enough information to be useful when coding - but you can pretend you know what you're talking about in suitably geeky company. More seriously, it will give you a very rough overview to give some context if you choose to investigate a particular feature further. (See also: Bluffer's Guide to C# 2.)

Each of the major features of C# 3 is here, with:

Automatic properties

Description

Automatic properties are a simple way to write properties which just get and set their values directly from/to a backing variable. For example, this code:

string name;
public string Name
{
    get { return name; }
    set { name = value; }
}

can be written in C# 3 like this:

public string Name { get; set; }

You can specify separate access levels for the getter and the setter, just like in C# 2.

Extra Bluff Power

Call their bluff (untrue statements)

Object and collection initializers

Description

Object initializers allow you to set the properties of an object very simply at construction time. Collection initializers are similar, allowing you to populate a collection. Examples:

// Object initializer
ProcessStartInfo psi = new ProcessStartInfo 

    FileName="Notepad.exe"
    Arguments="c:\\autoexec.bat",
    UseShellExecute=true
};
  
// Collection initializer for List
List<string> words = new List<string>
"the""quick""brown""fox""jumped""over""the""lazy""dog" };
  
// Collection initializer for Dictionary
Dictionary<string,int> ages = new Dictionary<string,int>
{
    { "Jon", 31 },
    { "Holly", 32 },
    { "Tom", 4 }
};

Extra bluff power

Call their bluff (untrue statements)

Implicitly typed local variables and arrays

Description

Local variables declared with var are treated as if they were declared with the type of the expression used to initialize the variable. Arrays can be initialized without specifying the type, and the type is inferred from the elements of the initializer. Examples:

// name is of type System.String
var name = "Jon";
// Initializer can use properties, methods etc
var time = DateTime.Now;
  
// Array type is inferred to be System.String
string[] words = new[] {"hello""there"};

Extra bluff power

Call their bluff (untrue statements)

Anonymous types

Description

Anonymous types persuade the compiler to create types with appropriate constructors and read-only properties, and then create instances of the type. These are primarily used within query expressions, but can be used elsewhere. Example:

var person = new { Name="Jon", Age=31 };
  
string name = person.Name;
int age = person.Age;

Extra bluff power

Call their bluff (untrue statements)

Lambda expressions

Description

Lambda expressions (expressions with => in them) are similar to anonymous methods in C# 2. They allow closures to be expressed simply, and can be converted into delegates or expression trees (see next point). For example, List<T> contains a ConvertAll method taking a delegate. To convert a List<int> into a List<double>, where each value in the resulting list is half the corresponding value in the original list, we could write:

List<int> original = new List<int> { 0, 1, 2, 3, 4, 5 };
List<double> halved = original.ConvertAll (x => x/2.0);

Extra bluff power

Call their bluff (untrue statements)

Expression trees

Description

Expression trees are a way of expressing logic so that other code can interrogate it. When a lambda expression is converted into an expression tree, the compiler doesn't emit the IL for the lambda expression; it emits IL which will build an expression tree representing the same logic. This is how LINQ providers such as LINQ to SQL work - it converts expression trees into SQL, effectively.

Extra bluff power

Call their bluff (untrue statements)

Extension methods

Description

Extension methods are a piece of syntactic sugar to make it look like you're calling an instance method on a value when actually you're calling a static method, passing that value as the first parameter. They're really important when it comes to query expression translation, and are useful in other ways too. Example:

public static class Extensions
{
    public static string Reverse(this string x)
    {
        char[] c = x.ToCharArray();
        Array.Reverse(c);
        return new string(c);
    }
}
...
string greeting = "hello world";
string backwards = greeting.Reverse();
Console.WriteLine(backwards); // Prints "dlrow olleh"

Extra bluff power

Call their bluff (untrue statements)

Query expressions

Description

Query expressions are a type of syntax somewhat unlike the rest of C#. It is transformed into non-expression-query C# and then normal compilation is applied. For instance, a query expression of:

var query = from word in words
            where word.Length > 4
            select word.ToUpper();

is translated into:

var query = words.Where(word => word.Length > 4)
                 .Select(word => word.ToUpper());

The above would then typically use extension methods to implement the effective query.

Extra bluff power

Call their bluff (untrue statements)