TLS320: C# Language Enhancements

TLS320: C# Language Enhancements

  • Comments 2

Generics are strongly-typed template mechanism. They enable you to create classes such as collections without requiring boxing. Generics offer type checking, no boxing and no downcasts, as well as reducing code bloat. Generics are instantiated at run-time, not compile-time and are checked at declaration, not instantiation. (In comparison, C++ templates are created at compile-time and checked when instantiated.) The strongly-typed nature of generics thus results in fewer hard-to-debug errors and better runtime type information. Generics are being introduced in Java, but they are purely syntactic sugar - when compiled, all the type parameters are thrown away and replaced with casting etc.

Type parameters can be applied to class, struct, interface and delegate types. You can declare:

   class Dictionary<K, V> { ... }
   Dictionary <string, Customer> customerLookupTable;
   Dictionary <string, List<Order>> orderLookupTable; 

Type parameters can also be applied to methods:

   public static void SortArray<T>(T[] array) { ... }
   string names[];
   SortArray(names); // notice that the type parameter is inferred

Type parameters can also have constraints, e.g.

   class Dictionary<K, V> where K : IComparable, new()
Here K must implement IComparable and a parameterless public default constructor. A constraint such as this can be verified at compile-time.

Generics are invariant, meaning that they have no intrinsic connection to each other within the class hierarchy. This is a deliberate decision due to the performance cost of implementing covariance. Interfaces can be used for type neutrality, however. On the subject of performance, a List<int> runs over twice as fast as the existing alternative - an ArrayList containing int objects. This is because it no longer requires all the boxing and unboxing to take place.

You are not permitted to assign null to a generic field, since there are no guarantees that it is nullable. Instead, you can write something like:

   T y = T.default; // 0 or null, depending on val/ref

Generics are not just a C# language feature - they are embedded deep within the CLR. There's a new namespace System.Collections.Generic which contains generic implementations of the standard classes, interfaces, base classes. Reflection is also supported on generics.

One fantastic new class is System.Nullable<T>, which provides nullability for any type. This is a struct that combines a T with a bool; there are implicit conversions from null to Nullable<T> and T to Nullable<T>.

Anonymous Methods
Today, event handlers are a lot of work. You have to create a separate method to handle an event. Instead, anonymous methods allow code blocks to be inserted in place of a delegate. The delegate type is automatically inferred. If you don't care about the arguments that the delegate is providing to you, you can provide a parameterless method; alternatively you can add parameters.

For instance:

   button.Click += delegate(object sender, EventArgs e) {

Anonymous methods are more or less the same as lambda-functions in Lisp - a higher-order function, to use functional programming terminology.

The foreach statement relies on an enumerator pattern. This is hard to write, but it makes the enumeration itself easy to access. Iterators provide a method that incrementally computes and returns a sequence of values. For instance:

   public IEnumerator GetEnumerator() {
      for (int i=0; i < count; i++) 
         yield return elements[i]; 

You can use these to implement the GetEnumerator() method or to create another method that returns an IEnumerable. You can then write something like:

   foreach (Item x in Items.Subrange(10, 20)) { ... }

Partial Types
Partial types allow you to split the implementation of a class, interface or struct into multiple separate source files. At compile-time, the compiler merges the partial classes together and compiles the output.

The biggest benefit here is that you can have partial types that span both auto-generated and hand-written code, and indeed this paradigm is used in the code-beside classes in ASP.NET and Windows Forms in Whidbey. A Whidbey WinForm no longer has all the auto-generated regions, because the code can be split out into a different class file (Form1.Designer.cs).

Other Enhancements
Static classes enable you to create classes containing only static members; the compiler can then check that this is the case. A static class does not need to create a private constructor to prevent instantiation. System.Console and System.Environment are good examples of this.

Properties can now have different accessibility for get {...} and set {...}. Typically set {...} is more restricted than get {...}.

Additional minor features include namespace aliases, pragma warnings and fixed size buffers. These are documented in the C# 2.0 language specification.

Page 1 of 1 (2 items)