C# - What's new in C# 2.0?

You will need Visual Studio 2005 or higher. (Released April 2005). .NET Framework. 2.0.



1) Generics

C++ has template classes. C# now has generics.


  // The old way. System.Collections.ArrayList
  var al = new ArrayList();
  al.Add(20);
  al.Add("Jane");
  
  var aNumber = (int)al[0];
  var aString = (string)al[1];
  
  // The new way. System.Collections.Generic
  var intList = new List<int>();
  intList.Add(20);
  var aNumber = intList[0];
  

2) Anonymous methods

Anonymous methods, in contrast to Named Methods, have no name. They are declared using the delegate keyword, and can be used in any place that a Named Method is valid.

Anonymous methods are used to write inline code.


  void Test()
  {
      var t = new System.Timers.Timer();
      t.Interval = 1000;
  
      t.Elapsed += TimerElapsed; // Using a Named Method
  
      // Using an anonymous method
      t.Elapsed += delegate(object sender, ElapsedEventArgs e)
      {
          Console.WriteLine("{0}: Tick - Anon", AppDomain.GetCurrentThreadId());
      };
  
      t.Start();
  
      Thread.Sleep(3000);
  }
  
  // This is a Named Method
  void TimerElapsed(object sender, ElapsedEventArgs e)
  {
      Console.WriteLine("{0}: Tick - Named", AppDomain.GetCurrentThreadId());
  }
  

3) Nullable types


A nullable type can represent all of the values of the underlying type, e.g. int, but can also have the value null.
This allows an additional state of value not set.


  void TestNullable()
  {
      System.Nullable<int> age;
      // OR
      int? age;
  
  
      age = 22;
  
      if (age.HasValue)
      {
          Console.WriteLine("Age is {0}", age.Value);
      }
  
      int ageValue = age.GetValueOrDefault();
  }
  

4) Partial types


Allows the definition of a class, struct or interface, to be split over multiple source files.


  // Program1.cs
  partial class Program
  {
      static void Main(string[] args)
      {
          // main code here
      }
  }
  

  // Program2.cs
  partial class Program
  {
      void HandleError(Exception ex)
      {
          // error handling code here
      }
  }
  

5) Iterators


Easily create IEnumerable collections using the yield return keyword.


  void Test1()
  {
      // example 1
      var primes = FivePrimes();
      foreach(int prime in primes)
      {
          Console.WriteLine(prime);
      }
  
      // example 2
      var days = new DaysOfTheWeek();
      foreach (string day in days)
      {
          Console.WriteLine(day);
      }
  }
  
  // using a function
  IEnumerable<int> FivePrimes()
  {
      yield return 1;
      yield return 3;
      yield return 5;
      yield return 7;
      yield return 9;
  }
  
  // using a class
  public class DaysOfTheWeek : IEnumerable
  {
      string[] m_Days = { "Sun", "Mon", "Tue", "Wed", "Thr", "Fri", "Sat" };
  
      public IEnumerator GetEnumerator()
      {
          for (int i = 0; i < m_Days.Length; i++)
          {
              yield return m_Days[i];
          }
      }
  }
  

6) Getter/setter separate accessibility


You can now use different accessibility levels on get and set property acessors.


  class MyClass
  {
      string _name;
  
      public string Name
      {
          // note: as always, this has the same accessibility as the parent property, in this case public
          get
          {
              return _name;
          }
          // protected = accessibility is limited to the containing type and those derived from it
          protected set
          {
              _name = value;
          }
      }
  }
  

7) Method group conversions


Simplified delegate syntax. Assign a MethodGroup to a delegate.


  delegate void LogDelegate(string message);
  
  private void LogMethod(string message)
  {
      Console.WriteLine(message);
  }
  
  private void TestMethod1()
  {
      // old syntax
      LogDelegate d1 = new LogDelegate(LogMethod);
  
      // new syntax
      LogDelegate d2 = LogMethod;
  
      d1("Test");
      d2("Test");
  }
  

8) Co- and Contra-variance for delegates


The terms covariance and contravariance describe how the compiler matches a method signature to a type.


The prefix co- means with. The prefix contra- means against. And variance means a deviation or difference.

So:
co-variance == with the difference (more derived).
contra-variance == against the difference (less derived).


Covariance allows a method to have a more derived return type than that of the original (delegate) type.

Contravariance allows a method to have less derived arguments than that of the original (delegate) type.


  delegate object HandleExceptionDelegate(ApplicationException e);
  
  void Test1()
  {
      HandleExceptionDelegate del1 = HandleException1; // co-variant
      HandleExceptionDelegate del2 = HandleException2; // contra-variant
  }
  
  // co-variant
  // return type is more derived. more specific. more different.
  string HandleException1(ApplicationException ex)
  {
      return null;
  }
  
  // contra-variant
  // argument list is less derived. less specific. less different.
  object HandleException2(Exception ex)
  {
      return null;
  }
  

9) Static classes


Static classes now have full compiler support.

Prior to C# 2.0, you would define an instance class with static methods and a private constructor (to prevent instantiation).

Static classes:
  • Contain only static members
  • Cannot be instantiated
  • Are sealed (they cannot be derived from)
  • Cannot contain instance constructors

  static class MyMath
  {
      private static double PI = 3.14159;
  
      // static ctor
      static MyMath()
      {
      }
  
      public static double GetPi()
      {
          return PI;
      }
  }
  
  void Test1()
  {
      var pi = MyMath.GetPi();
  }
  

Ads by Google

Ask a question, send a comment, or report a problem - click here to contact me.

© Richard McGrath