C_ 2.0

Document Sample
C_ 2.0 Powered By Docstoc
					C# 2.0 New Features

       Namespaces and Aliases
 The namespace keyword is used to declare a
 Making software components reusable can
  result in naming collisions (two classes defined
  by two programmers can have the same name).
      using System.Collections;
 Aliases allows you to effectively name an assembly reference when
  you compile the code, and use that name to disambiguate between
 Aliases allow you to disambiguate between names which have been
  declared within an already used namespace and names which
  belong to the "root" namespace. This is achieved with the
  predefined alias of global

                                  namespace ISE Exam2004.dll
 using System;                       public class PGUI
 extern alias Exam2005;                 public void Exam()
 extern alias Exam2004;              }

 class Program                    }
namespace ISE  Exam2005.dll
    public class PGUI
       public void Exam() {...}
        Property Access Specifiers
 Prior to 2.0, it was impossible to declare a property with one access
   level for the "get" accessor and a different access level for the "set”

    public class Test
        string someProperty;
         public string SomeProperty
                 return someProperty;
             private set
                 someProperty = value;
    }                                                                        4
 A name must start with a letter or “_”.
 Case sensitive (eg. letter, Letter)
 Unicode characters: characters from any languages
  other than English, int \u03C0;
 Name conventions to write C# programs:
    Properties, methods and classes: begin with uppercase
     letters (eg Length, DrawLine, etc.)
    Local variables and fields that are not visible outside their
     class: begin with lowercase letters (eg. len)
    Each word in composite words begins with an uppercase
     letter (eg WriteLine).
    Void methods begin with a verb (eg. DrawEllipse)
    Boolean methods begin with an adjective (eg. Empty)
    Other names should begin with a noun (eg. Collection)
 Value Type:
   struct, enumeration, numeric types (integral, floating-
    point, decimal), bool, etc.
   Assigning one value type variable to another copies
    the contained value
 Reference Type:
   class, interface, delegate, object, string.
   Variables of reference types, referred to as objects,
    store references to the actual data
 Void
 Nullable Type
 Pointer Type
     Variables & Built-in Types
 object, bool
 byte (0 to 255), sbyte (-128 to 127)
 short, ushort, int, uint, long, ulong
 float, double, decimal
 char, string
object o = 5, o2 = 'c', o3 = "hi";
bool b1 = false, b2 = (5 < 2);
long l = 12000L; float f = 1.2F; decimal d =
using uninitialised variables in C# is not allowed
                   Nullable Types
 Reference types (eg. instances of classes) already support the null
 Nullable types represent value-type variables that can be assigned
  the value of null.
 T? is shorthand for System.Nullable<T>.

  int? x = null;   int y;
  y = (int) x; //throws InvalidOperationException
  y = x.Value; //throws InvalidOperationException
  if (x.HasValue) // false, x has no value
     y = x.Value;
  y = x.GetValueOrDefault(); // y = 0

       Nullable Type Example
int? a = 10;
int? b = null;
a++; // now a is 11.
a = a * 2; // now a is 22.
a = a + b; // now a is null.
int? i = 5;
Type t = i.GetType(); // System.Int32

if (i is int) // true
   i = 7;

    Nullable Type Conversions
Implicit conversion (no cast required) from a non-nullable type to its
equivalent nullable type
Explicit conversion (cast requried) from a nullable type to its
equivalent non-nullable type
The boxed type of a nullable value is the boxed type of the
equivalent non-nullable value. If you box a value which is already
null (i.e. HasValue is false), the result is null.

int i = 135;

int? x = i;                                   // int --> int?
double? y = x;                  // int? --> double?
int? z = (int?)y;               // double? --> int?
int j = (int)z;                 // int? --> int

int? z = x.HasValue && y.HasValue ?
                   x.Value + y.Value : (int?) null;                      10
     Null Coalescing Operator ??
 a ?? b is similar to a==null ? b : a. The type of a has to be a nullable type or
   a reference type, and the type of b has to be a suitable type

 The result of a ?? b is
     if a is non-null, b is null, result is a;
     If both a and b are non-null, it is a

 When a is of a nullable type (value=null) and b is of a non-nullable type, a
   ?? b returns a non-nullable value, provided the appropriate implicit
   conversions exist between the operand types

       int? x = 5;
       int? y = 7;
       int? z = x ?? y;
       int i = z ?? -1;

 The type of x ?? y is int?, but the type of z ?? -1 is int.

     Unsafe Code and Pointers
 In an unsafe context, a type may be a pointer type as
  well as a value type or a reference type.
       type* identifier     eg.   int* num;
 The value of the pointer variable of type myType* is the
  address of a variable of type myType.
 A pointer cannot point to a reference or to a struct that
  contains references because it is possible for an object
  reference to be garbage collected even if a pointer is
  pointing to it
 Pointer types do not inherit from object and no
  conversions exist between pointer types and object.
 Boxing and unboxing do not support pointers

      Unsafe Code and Pointers
 A pointer type declaration takes one of the following forms

        type* identifier;
        void* identifier;        // allowed but not recommended

 unsafe // may only appear if compiling with /unsafe
       int* p1, p2, p3;         // ok
       int *p1, *p2, *p3;       // Invalid in C#

        int x = 5;
        int* px = &x                    // &: address-op operator
        int y = *px;                    // value
        string s = px->ToString();      // address
           Boxing & Unboxing
 Boxing
 object o1 = 5, o2 = ‘c’;
 ArrayList al = new ArrayList();
 al.Add(5); al.Add("hi");
 Unboxing
 int i = (int) o1;
 char c = (char) o2;
 string s = (string) al[1];

                     Keyword as
 as only performs reference conversions and
  boxing conversions

expression as type
   expression is type ? (type) expression : (type) null

object    oi   =   5;
object    os   =   "st";
string    si   =   oi as string; // null
string    ss   =   os as string; // ss = "st"
                Keyword is
 is to check whether the run-time type of an object
  is compatible with a given type

object o1 = 5, o2 = 's';
char c = 0;
// throws InvalidCastException
c = (char) o1;

// this is fine
if (o2 is char)
   c = (char) o2;
                   Nested Class
 Nested types can see all the members of their closing
  type, both private and public ones.
 External types only see nested types if they are declared
  as public.
 Fields of inner types and outer types belong to different
  objects. We must specify the object to which they belong
  when we want to access them. In Java, inner classes can
  access fields of outer class

  public class MyClass
       private class NestedClass
           Class Accessibility
 public: access is not restricted
 private: access is limited to the containing type
 protected: access is limited to the containing
  class or types derived from the containing class
 internal: access is limited to the current assembly
 protected internal: access is limited to the
  current assembly or types derived from the
  containing class

    Abstract Class, Abstract Methods
          and Virtual Methods
 Abstract class is normally used as a base class and never
    intended to instantiate any objects.
   The use of polymorphism requires declaring virtual or
    abstract methods and properties in the abstract base class
    and overriding them in the derived classes.
   Any class with an abstract method in it must be declared
   Abstract methods do not have an implementation in the
    abstract base class and every concrete derived class must
    override all base-class abstract methods and properties
    using keyword override.
   Virtual methods have an implementation in the abstract
    base class and its derived classes have an option of
    overriding the method
Abstract class:

public abstract class AbstractClass
       public AbstractClass()
       public abstract int AbstractMethod();
       public virtual int VirtualMethod()
          return 0;
}                                              20
Derived class:

public class DerivedClass : AbstractClass
      public DerivedClass()
      public override int AbstractMethod()
              return 0;
      public override int VirtualMethod()
              return base.VirtualMethod ();
}                                             21
                  Sealed Class
 The keyword sealed is applied to classes and methods to
    prevent overriding and inheritance.
   A method declared sealed cannot be overridden in a
    derived class
   Static methods and private methods are implicitly sealed.
   Recall that a method can be overridden if it is declared
    either virtual or abstract. The keyword sealed is not
    applied to these cases. However, we can use the keyword
    sealed for methods we have overridden and we do not
    want to override it in further derived classes.
   A sealed class cannot be a base class since it cannot be
    inherited and hence it cannot have any derived classes.
   All methods in a sealed class are sealed implicitly

         Sealed Class Example
sealed class SealedClass
       public int x;
       public int y;
class MyClass
       SealedClass sc = new SealedClass();
       sc.x = 10;
       sc.y = 20;
class InClass : SealedClass // error: cannot inherit
{ }

                Partial Class
 All source code for a type is normally in a single
 Sometimes a type becomes large enough that this
  is an impractical constraint.
 Partial types allow classes and interfaces to be
  broken into multiple pieces stored in different
  source files for easier development and
 Additionally, partial types allow separation of
  machine-generated and user-written parts of
  types so that it is easier to augment code
  generated by a tool
          Partial Class Example
public class Student            public partial class Student {
                                  private int studentID;
{                                 public Student () {
       private int studentID;            ...
       private int name;          }
       public Student () {
                                public partial class Student {
                                  private int name;
       public ChangeName() {      public ChangeName() {
              ...                        ...
       }                          }
       public ChangeID () {       public ChangeID () {
              …                   }
       }                        }
}                                                                25
 An interface definition begins with a keyword interface and
  contains a set of public methods and properties that have
  no default implementation to inherit.
 An interface must be declared as public.
  public interface IStudent
       int StudentID {get; set;}
       void AddSubject(string subjectName);
 Interfaces can be implemented by classes.
 An interface defines a contract. This means that a class
  that implements an interface must provide
  implementations for every method and property specified
  in the interface definition.                             26
  Class implementing Interface
public class Student : IStudent
  private int studentID = 0;
  private ArrayList subjects = null;
  public Student() {}
  public int StudentID {
       get { return studentID; }
       set { studentID = value; }
  public void AddSubject(string subjectName) {
}                                                27
                  Generic Class
public class NonGeneric             public class Generic<T>
{                                   {
  object item;                         T item;
  public object Item                   public T Item
  {                                    {
       get {                                 get {
               return item;                        return item;
       }                                     }
       set {public class MyClass()           set {
               item = value;
              NonGeneric ng = new NonGeneric ();
                                                   item = value;
       }                                     }
              Generic<int> g = new Generic<int>();
  }         }                          }
}                                   }                              28
                    Generic Class
 Advantages
    Type checking, no boxing, no downcasts
    Increased type reuse (typed collections)
 How are generics implemented?
    Checked at declaration, not instantiation
    Instantiated at run-time, not compile-time
    Exact run-time type information
    Work for both reference and value types
 Collection classes
    Stack<T>, Queue<T>, Dictionary<U, V>
 Collection interfaces
    IEnumerable<T>, ICollection<T>, IDictionary<U, V>
 When writing custom business objects, it was a
   recommended practice to define strongly typed collections
   derived from System.Collections.CollectionBase.

        Type-safe Generic ArrayList
public class ObjectList<ItemType> : CollectionBase
private ArrayList list = new ArrayList();
public int Add(ItemType value)
{ return list.Add(value); }
public void Remove(ItemType value)
{ list.Remove(value); }
public ItemType this[int index]
{ get
    { return (ItemType)list[index]; }
    { list[index] = value; } } }

Using the ObjectList class to create an ArrayList collection that supports only strings
ObjectList<string> list = new ObjectList<string>();
list.Add(4); // error                                                                     30
                  Simple Generic
using System;
using System.Collections.Generic;
class Test
    static void Main()
        IList<string> list = new List<string>();
        // Wouldn't compile - the list is strongly typed,
        // so there's effectively only an Add(string) method
        // list.Add(new object());

        // No need for a cast here - again, the list is
        // strongly typed, so the indexer is of type string.
        string x = list[0];

               Generic Methods
static void AddMultiple<T>(List<T> list, params T[] values)
   foreach (T value in values)

void MyMethod()
  List<int> list = new List<int>();
  AddMultiple<int>(list, 2, 4, 6);

delegate inference,
covariance/contravariance and
anonymous methods.

                 Delegate Inference
using System;
delegate void SomeAction();
class Test
static void Main(string[] args)
     // Without using delegate inference
     SomeAction oldStyle = new SomeAction (SayHello);
     // Now using delegate inference
     SomeAction newStyle = SayHello;
static void SayHello()
     Console.WriteLine ("Hello");

   Arrays of reference-types are covariant: string[] is a subtype of object[], although with some caveats:

     // A is a single-element array of System.
     String. string[] a = new string[1];
     // B is an array of System. Object
     object[] b = a;
     // Assign an integer to b. This would be possible
       if b really were // an array of objects, but
       since it really is an array of strings, // we
       will get an ArrayTypeMismatchException with the
       following message: // "Attempted to store an
       element of the incorrect type into the array".
     b[0] = 1;
   Note: In the above case you can read from b without problem. It is only when trying to write to the
    array that you must know its real type.
   Arrays of value-types are invariant: int[] is not a subtype of double[].
   In the C# programming language, support for both return-type covariance and parameter
    contravariance for delegates was added in version 2.0 of the language. Neither covariance nor 35
    contravariance are supported for method overriding.}
   Covariance allows you define a delegate with a return type of a base class that can be used by its
    derived type. In the example below, you define a delegate that returns the base class type
    Automobile, but you can still use that same delegate to return a derived Car object...

class Automobile {
    public Automobile CreateAuto() { return new Automobile(); }

class Car : Automobile {
    public Car CreateCar() { return new Car(); }

class Application {
    public delegate Automobile Create();
    public static void Foo(Create c) {
    public static void Main() {
         Create c1 = new Create(new Automobile().CreateAuto);
    //In VS.NET 2003, the following exception would occur on the next line of code:
   // "Method 'Car.CreateCar()' does not match delegate
   //'Automobile Application.Create()"
      Create c2 = new Create(new Car().CreateCar);
   This example demonstrates how delegates can be used with methods
    that have parameters of a type that are base types of the
    delegate signature parameter type. With contravariance, you can
    now use one event handler in places where, previously, you would
    have had to use separate handlers.
   For example, you can now create an event handler that accepts an
    EventArgs input parameter and use it with the Button.MouseClick
    event that sends a MouseEventArgs type as a parameter, and also
    with TextBox.KeyDown event that sends a KeyEventArgs parameter.
    System.DateTime lastActivity;
    public Form1()
        lastActivity = new System.DateTime();
        this.textBox1.KeyDown += this.MultiHandler; //works with
        this.button1.MouseClick += this.MultiHandler; //works with
    // Event hander for any event with an EventArgs or
    // derived class in the second parameter
    private void MultiHandler(object sender, System.EventArgs e)
    {                                                                37
        lastActivity = System.DateTime.Now;
       Anonymous methods
using System;
delegate void SomeAction();
class Test
    static void Main(string[] args)
         SomeAction instance = delegate
      { Console.WriteLine(args[0]); };

                 Captured variables
Purpose: To make local variables from the method declaring an anonymous method
    available within the delegate itself.
Static and instance variables of the class don't need to be captured
                                                             A local variable in
using System;                                              MakeDelegate used to
                                                           print a new random
delegate void SomeAction();                                number every time it's
class Test                                                 invoked.
{                                                            The scope of that
    static void Main(string[] args)                        variable even exist
    {                                                      outside MakeDelegate,
        SomeAction instance = MakeDelegate();              because the compiler
        instance();                                        compiles it into an
        instance();                                        instance variable in a
    }                                                      new type behind the
     static SomeAction MakeDelegate()                      scenes.
         Random rng = new Random();
          return delegate { Console.WriteLine (rng.Next()); };
}                                                                                39
               Captured variables
Multiple local variables used in the delegate:
using System;
delegate void SomeAction();
class Test                                                Out of two variables,
    static void Main(string[] args)                     one is shared and
    {                                                   another isn’t.
        SomeAction[] instances = new SomeAction[10];      Two extra types are
        int x;                                          created - one with an x
        for (int i=0; i < 10; i++)                      variable, and one with a
        {                                               y variable and another
            x=0;                                        variable referring to an
            int y=0;
            instances[i] = delegate                     instance of the first
            {                                           extra type.
                Console.WriteLine ("{0}, {1}", x, y);     The delegate
                x++;                                    implementation is a
            };                                          member of the second
        }                                               type, and each instance
        instances[0](); // Prints 0, 0                  of the second type has
        instances[0](); // Prints 1, 1
        instances[0](); // Prints 2, 2                  a reference to the same
        instances[1](); // Prints 3, 0                  instance of the first type.
        instances[2](); // Prints 10, 0                                        40
     Iterators and yield statement
 yield statements allow you to write iterators "inline" in a single method, with
  the compiler doing all the hard work of keeping track of state behind the
 yield statements are only valid in a method/operator/property which returns
  one of IEnumerable, IEnumerable<T>, IEnumerator or IEnumerator<T>.
 You can't mix and match - if a member uses yield statements, it can't use
  normal return statements too.
 There are two types of yield statements – Foo() is only called once, the
    yield return (for returning the next item)        compiler has effectively built a
    yield break (to signify the end of the iterator). state machine
   using System;
     using System.Collections;
     class Test
                                                     MoveNext() is called implicitly by
         static void Main(string[] args)
                                                     the foreach statement
             foreach (string x in Foo())             Every time MoveNext() is called
                 Console.WriteLine (x);              on the iterator execution
         }                                           continues from where it had got to
         static IEnumerable Foo()                    in what we've declared as the
             yield return "Hello";                   Foo() method, until it next reaches
             yield return "there";                   a yield statement.
         }                                                                          41
     Iterators and yield statement
using System;
using System.Collections;
class Test
    static void Main(string[] args)
        NameAndPlaces t = new NameAndPlaces("Jon", new string[]{"London", "Hereford",
    "Cambridge", "Reading"});
    foreach (string x in t)
            Console.WriteLine (x);                       Can't put a yield statment in a
    }                                                    finally block, try block if there's
                                                          a catch block, and you can't use
public class NameAndPlaces : IEnumerable
{                                                         unsafe code.
    string name;
    string[] places;
                                                          However, you can use normal
    public NameAndPlaces (string name, string[] places)
    {                                                     looping, access other variables
        this.name = name;                                 usually by implementing
        this.places = places;
    }                                                     IEnumerable
    public IEnumerator GetEnumerator()
    {                                                     yield break is used to stop
        yield return "My name is "+name;
        yield return "I have lived in: ";                 iterating
        foreach (string place in places)
            yield return place;                                                         42