C# in Depth

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

Bluffer's Guide to C# 2

Obviously C# in Depth teaches the new features of C# 2 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# 3.)

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

Generics

Description

Generics allow types and methods to be parameterised by other types. Frankly it's a difficult idea to describe in few words, but it's best shown with an example:

// Without generics: ArrayList
ArrayList listOfStrings = new ArrayList();
listOfStrings.Add("first");
listOfStrings.Add("second");
listOfStrings.Add("third");
listOfStrings.Add(4); // Eek!
  
// Cast is necessary, as indexer just returns object
string y = (string) listOfStrings[1];
  
// This will blow up when it reaches 4
foreach (string x in listOfStrings)
{
    Console.WriteLine(x);
}
  
// With generics: List<T>
List<string> listOfStrings = new List<string>();
listOfStrings.Add("first");
listOfStrings.Add("second");
listOfStrings.Add("third");
// Compilation error! Compiler knows the list should only contain strings
listOfStrings.Add(4);
  
// No cast necessary: the list can only contain strings
string y = listOfStrings[1];
  
// This is guaranteed to be okay
foreach(string x in listOfStrings)
{
    Console.WriteLine(x);
}

Extra bluff power

Call their bluff (untrue statements)

Nullable types

Nullable types are value types which are wrappers round other value types (where the other type is specified with generics), allowing a "null value" to be represented. They are particularly useful with database code, as databases often have nullable columns for numbers, dates and times, GUIDs etc - all of which are value types in .NET. The Nullable<T> structure is at the heart of nullable types, and C# has extra syntactic sugar with the "?" modifier and various other neat features. For example:

// x, y and z are the same type
int? x = null;
Nullable<int> y = 10;
  
int? z = x+y;
  
if (z==null)
{
    Console.WriteLine("Null result");
}
else
{
    // Note: not nullable
    int result = z.Value;
    Console.WriteLine("Result: {0}", result);
}

Extra bluff power

Call their bluff (untrue statements)

Delegates (method group conversions and anonymous methods)

Description

Delegates in C# 2 have a number of improvements over C# 1. The most important two features are implicit method group conversions and anonymous methods, both of which make it easier to create new instances of delegate types. For example:

public void Foo()
{
    // Do some stuff
}
  
// C# 1 code:
ThreadStart ts1 = new ThreadStart(Foo);
  
// C# 2 code, implicit method group conversion:
ThreadStart ts2 = Foo;
  
// C# 2, anonymous method:
ThreadStart ts3 = delegate { Console.WriteLine("Hi!"); };

There's a lot more to anonymous methods than meets the eye, by the way...

Extra bluff power

Call their bluff (untrue statements)

Iterator blocks

Description

Iterator blocks allow IEnumerable<T>, IEnumerable, IEnumerator<T> and IEnumerator to be implemented very simply in C# code. For example, the code below will print out "start", "0", "1", "2", "3", "4", "end".

IEnumerable<string> GetSequence()
{
    yield return "start";
    for (int i=0; i < 5; i++)
    {
        yield return i.ToString();
    }
    yield return "end";
}
...
foreach (string x in GetSequence())
{
    Console.WriteLine(x);
}

Extra bluff power

Call their bluff (untrue statements)

Partial types

Partial types allow a single type to be built from multiple source files. This is particularly useful with autogenerated code, where the tool (e.g. a GUI designer) can "own" one file, and the developer can work in a different one. The partial keyword is used to indicate that the type may span multiple files.

// Partial1.cs
public partial class Partial
{
    public void Foo()
    {
        Bar(); // Calls into a method declared in a different type
    }
}
  
// Partial2.cs
public partial class Partial
{
    void Bar()
    {
        Console.WriteLine("Hi!");
    }
}

Extra bluff power

Call their bluff (untrue statements)