Www.itu.dk Advanced C#, part I Niels Hallenberg IT University of Copenhagen BAAAP – Spring 2009.

38
www.itu.dk Advanced C#, part I Niels Hallenberg IT University of Copenhagen BAAAP – Spring 2009

Transcript of Www.itu.dk Advanced C#, part I Niels Hallenberg IT University of Copenhagen BAAAP – Spring 2009.

Page 1: Www.itu.dk Advanced C#, part I Niels Hallenberg IT University of Copenhagen BAAAP – Spring 2009.

www.itu.dk

Advanced C#, part I

Niels HallenbergIT University of Copenhagen

BAAAP – Spring 2009

Page 2: Www.itu.dk Advanced C#, part I Niels Hallenberg IT University of Copenhagen BAAAP – Spring 2009.

www.itu.dk

Outline

Advanced C#, Part I• Interfaces• Collections and Generics• Delegates and Lanbdas

For our project• High Quality Test Data• Stubs

Page 3: Www.itu.dk Advanced C#, part I Niels Hallenberg IT University of Copenhagen BAAAP – Spring 2009.

www.itu.dk

Interfaces

– Interfaces and Abstract Base Classes

– What are Interfaces used for?• You have a single hierarchy where

only a subset of the derived types have a common behavior

• The same behavior must be implemented on types in different hierarchies with only the System.object as common parent class.

Why do we need both?

Functionality that must be supported

by some type.

You can’t enable four-wheel drive

on all cars.

Illustrated by many built in interfaces, fx

IEnumerable, IEnumerator, ICloneable,

ICompareable and IComparer

Page 4: Www.itu.dk Advanced C#, part I Niels Hallenberg IT University of Copenhagen BAAAP – Spring 2009.

www.itu.dk

Single Hierarky Interface• Abstract Vechicle class

public abstract class Vechicle { int numWheels; String vechicleName;

public Vechicle(int w, String n) { this.numWheels = w; this.vechicleName = n; }

public override String ToString() { return "Vechicle " + this.vechicleName + …; } public abstract int numPersons();} All sub classes must

have a numPersons method.

Page 5: Www.itu.dk Advanced C#, part I Niels Hallenberg IT University of Copenhagen BAAAP – Spring 2009.

www.itu.dk

Single Hierarky Interface• The ILicenseNo interface

public interface ILicenseNo { String LicenseNo {get; set;}}

• Some vechicles does have a license number

Page 6: Www.itu.dk Advanced C#, part I Niels Hallenberg IT University of Copenhagen BAAAP – Spring 2009.

www.itu.dk

Single Hierarky Interface• Cycle, Bike and Car classes

public class Cycle : Vechicle { public Cycle() : base(2, "cycle") { } public override int numPersons() { return 1; }}

public class Bike : Vechicle, ILicenseNo { private String licenseNo; public Bike(String licenseNo) : base(2, "bike") { this.licenseNo = licenseNo; } public String LicenseNo { get { return this.licenseNo; } set { this.licenseNo = value; } } public override int numPersons() { return 2; }}

It’s a sports cycle.

A Bike does have a license number

Required by the interface

Required by the Vechicle class

Page 7: Www.itu.dk Advanced C#, part I Niels Hallenberg IT University of Copenhagen BAAAP – Spring 2009.

www.itu.dk

Single Hierarky Interface• The Car class

public class Car : Vechicle, ILicenseNo { String licenseNo; public Car(String licenseNo) : base(4, "car") { this.licenseNo = licenseNo; } public String LicenseNo { get { return this.licenseNo; } set { this.licenseNo = value; } } public override int numPersons() { return 4; }}

A car does have a license number

Page 8: Www.itu.dk Advanced C#, part I Niels Hallenberg IT University of Copenhagen BAAAP – Spring 2009.

www.itu.dk

Single Hierarky Interface• Using the class hierarky

Vechicle[] vs = { new Cycle(), new Bike("RX 34213"), new Car("GC 45221") };

// Print all vechiclesforeach (Vechicle v in vs) Console.WriteLine(v.ToString() + " has " + v.numPersons() + " seats.");

A bike and Car got a license number

All vechicles can be pretty printed and got a

number of persons.

All sub-classes to Vechicle must implement numPersons.

• Using is and as.

Console.WriteLine("--- License Numbers ---");foreach (Vechicle v in vs) if (v is ILicenseNo) Console.WriteLine(v.ToString() + " has license number: " + (v as ILicenseNo).LicenseNo);

Test for class type

Type cast

Page 9: Www.itu.dk Advanced C#, part I Niels Hallenberg IT University of Copenhagen BAAAP – Spring 2009.

www.itu.dk

Single Hierarky Interface• Invalid Cast Exception

Console.WriteLine("--- Invalid Cast Exception ---");// Mk. array of vechicles with license numbertry { ILicenseNo[] xs = { (ILicenseNo)vs[0], (ILicenseNo)vs[1], (ILicenseNo)vs[2] };} catch (InvalidCastException e) { Console.WriteLine("Not all vechicles has a license no.");}

A Cycle class does not implement ILicenseNo.

Example file: SingleHierarkyInterface

Page 10: Www.itu.dk Advanced C#, part I Niels Hallenberg IT University of Copenhagen BAAAP – Spring 2009.

www.itu.dk

Explicit Named Interface• Same method name in a class and interface • Same method name in two or more interfaces. This require

Multiple Interface support.

// Interface for vechicles having an extra seats that can // be added, fx a side car on a Bike and a Cycle.public interface ISideCar { int numPersons();}

Return number of persons in side car.

• The Cycle and Bike class may have a side car.

public class Bike : Vechicle, ILicenseNo, ISideCar { … public override int numPersons() { return 2; } // There are room for one child or adult. int ISideCar.numPersons() { return 1; }}

numPersons required by abstract Vechicle

class

numPersons required by the side car

interface.

Example file: ExplicitlyNamedInterface

Page 11: Www.itu.dk Advanced C#, part I Niels Hallenberg IT University of Copenhagen BAAAP – Spring 2009.

www.itu.dk

Explicit Named Interface• A cycle can have two kids in a side car.

public class Cycle : Vechicle, ISideCar { public Cycle() : base(2, "cycle") { } public override int numPersons() { return 1; } // There are room for two kids. int ISideCar.numPersons() { return 2; }}

Return number of persons in side car.

Page 12: Www.itu.dk Advanced C#, part I Niels Hallenberg IT University of Copenhagen BAAAP – Spring 2009.

www.itu.dk

Explicit Named Interface• What version of numPersons is used below.

Vechicle[] vs = { new Cycle(), new Bike("RX 34213"), new Car("GC 45221") };

// Print vechicles with num persons – // side cars are not included.foreach (Vechicle v in vs) Console.WriteLine(v.ToString() + " has " + v.numPersons() + " seats.");

• The Cycle and Bike class may have a side car.

The numPersons method from the

abstract class Vechicle

foreach (Vechicle v in vs) if (v is ISideCar) Console.WriteLine(v.ToString() + " has " + ((v as ISideCar).numPersons() + v.numPersons()) + " seats including side car."); else Console.WriteLine(v.ToString() + " has " + v.numPersons() + " seats and no side car.");

We know that v supports the ISideCar

interface

Page 13: Www.itu.dk Advanced C#, part I Niels Hallenberg IT University of Copenhagen BAAAP – Spring 2009.

www.itu.dk

Single Inheritance Interface• An interface can inherit from another interface

public interface ISerialNo { String SerialNo { get; set; }}public interface ILicenseNo : ISerialNo { String LicenseNo { get; set; }}

All vechicles containing a serial number – most but

not baby cycles.

• A BabyCycle does not have any serial or license number.• A Cycle does have a serial number.• If a class has a license number, then there will also be a serial

number.

public class BabyCycle : Vechicle { … }public class Cycle : Vechicle, ISerialNo { … }public class Bike : Vechicle, ILicenseNo { … }public class Car : Vechicle, ILicenseNo { … }

Vechicles with a license number must

also have a serial number

Example file: SingleInheritanceInterface

Page 14: Www.itu.dk Advanced C#, part I Niels Hallenberg IT University of Copenhagen BAAAP – Spring 2009.

www.itu.dk

Single Inheritance Interface• Class Diagram having Single Inheritance

Page 15: Www.itu.dk Advanced C#, part I Niels Hallenberg IT University of Copenhagen BAAAP – Spring 2009.

www.itu.dk

Single Inheritance Interface• Find all objects that support ISerialNo.

foreach (Vechicle v in vs) if (v is ISerialNo) Console.WriteLine(v.ToString() + " has serial number: " + (v as ISerialNo).SerialNo);

A type that supports ILicenseNo will also support ISerialNo.

• Find all objects that support ILicenseNo. They will also support ISerialNo.

foreach (Vechicle v in vs) if (v is ILicenseNo) Console.WriteLine(v.ToString() + " has serial number: " + (v as ILicenseNo).SerialNo + " and license number: " + (v as ILicenseNo).LicenseNo);

A type that supports ILisenceNo does include the property SerialNo.

Page 16: Www.itu.dk Advanced C#, part I Niels Hallenberg IT University of Copenhagen BAAAP – Spring 2009.

www.itu.dk

Multiple Inheritance Interface• An interface can extend other interfaces.

public interface ISerialNo { String SerialNo { get; set; }}public interface ILicenseNo : ISerialNo { String LicenseNo { get; set; }}public interface IVechicleName { String Name { get; set; }}public interface IVechiclesMetaData : ILicenseNo, IVechicleName{ int VechicleId { get; } String ppMetaData();}

We give a vechicle a name, eg brand.

The Meta Data interface extends two other interfaces. There are no name splashes, but that will often be the case. Then use explicit naming.

Example file: MultipleInheritanceInterface

Page 17: Www.itu.dk Advanced C#, part I Niels Hallenberg IT University of Copenhagen BAAAP – Spring 2009.

www.itu.dk

Multiple Inheritance Interface• Class Diagram having Multiple Inheritance

Page 18: Www.itu.dk Advanced C#, part I Niels Hallenberg IT University of Copenhagen BAAAP – Spring 2009.

www.itu.dk

Multiple Inheritance Interface

• Find all objects that support IVedhicleMetaData and print the meta data.

Console.WriteLine("--- Meta Data ---");foreach (Vechicle v in vs) if (v is IVechiclesMetaData) Console.WriteLine( (v as IVechiclesMetaData).ppMetaData());

public class Bike : Vechicle, IVechiclesMetaData { … public String ppMetaData() { return "Meta data for " + this.name + " of type " + this.vechicleName + NewLine + " Serial number: " + this.serialNo + NewLine + " License number: " + this.licenseNo + NewLine + " Vechicle id: " + this.vechicleId + NewLine; }}

Page 19: Www.itu.dk Advanced C#, part I Niels Hallenberg IT University of Copenhagen BAAAP – Spring 2009.

www.itu.dk

Some Built In InterfacesA few interface examples:

– IEnumerable : An interface containing the method GetEnumerator. GetEnumerator returns an object implementing the interface IEnumerator

– IEnumerator : An interface containing methods necessary for the foreach construct, that is, Current, MoveNext and Reset.

– ICloneable : An interface containing a Clone method.There are no rules regarding deep and shallow implementations.

– IComparable : An interface containing a Compare method to compare the actual object.

– IComparer : An interface containing a CompareTo method to compare two objects.

Page 20: Www.itu.dk Advanced C#, part I Niels Hallenberg IT University of Copenhagen BAAAP – Spring 2009.

www.itu.dk

Some Built In Interfaces

Page 21: Www.itu.dk Advanced C#, part I Niels Hallenberg IT University of Copenhagen BAAAP – Spring 2009.

www.itu.dk

IEnumerable and IEnumerator

• A simple approach is to the a built in enumerator, in this case, in ArrayList.

VechicleContainer vContainer = new VechicleContainer();vContainer.addVechicle(new Cycle());vContainer.addVechicle(new Bike("RX 34213"));vContainer.addVechicle(new Car("GC 45221"));Console.WriteLine("--- Listing Forwards ---");foreach (Vechicle v in vContainer) Console.WriteLine(v.ToString());

public class VechicleContainer : IEnumerable { ArrayList vs; public VechicleContainer() { this.vs = new ArrayList(); } public void addVechicle(Vechicle v) { vs.Add(v); } public IEnumerator GetEnumerator() { return vs.GetEnumerator(); }

Built in enumerator

Page 22: Www.itu.dk Advanced C#, part I Niels Hallenberg IT University of Copenhagen BAAAP – Spring 2009.

www.itu.dk

IEnumerable and IEnumerator

• We can also make our own enumerator use yield.

Console.WriteLine("--- Listing Backwards ---");foreach (Vechicle v in vContainer.GetEnumeratorBackwards()) Console.WriteLine(v.ToString());

public class VechicleContainer : IEnumerable { ArrayList vs; public VechicleContainer() { this.vs = new ArrayList(); } public void addVechicle(Vechicle v) { vs.Add(v); }

// A Named Iterator public IEnumerable GetEnumeratorBackwards() { for (int i=vs.Count-1; i>=0; i--) yield return vs[i]; } The keyword yield makes the compiled code

remember the code location each time an element is returned. Computation starts at that

location when returning the next element.

The compiler will implicitly generate a class containing the

GenEnumerator method.

Page 23: Www.itu.dk Advanced C#, part I Niels Hallenberg IT University of Copenhagen BAAAP – Spring 2009.

www.itu.dk

IEnumerable and IEnumerator

• You can also code the enumerator your self.

public interface MyOwnGetEnumerator { IEnumerator GetEnumerator(); }

public class VechicleContainer : IEnumerable, IEnumerator, MyOwnGetEnumerator { … public void Reset() {Console.WriteLine("Reset.");this.i=-1;} public bool MoveNext(){Console.WriteLine("MoveNext"); i++; if (i < vs.Count) return true; else return false; } public object Current {get {Console.WriteLine("Current"); return this.vs[i];}}

IEnumerator MyOwnGetEnumerator.GetEnumerator() { return (IEnumerator)this; }}

Console.WriteLine("--- Listing with My Own Enumerator ---");foreach (Vechicle v in (MyOwnGetEnumerator)vContainer) Console.WriteLine(v.ToString());

Page 24: Www.itu.dk Advanced C#, part I Niels Hallenberg IT University of Copenhagen BAAAP – Spring 2009.

www.itu.dk

Collections

Classes of System.Collection:•ArrayList : Dynamically sized Array•Hashtable : Collection of objects identified by

a numeric key.•Queue : Standard FIFO queue•SortedList : Sorted list of key value pairs.•Stack : Standard LIFO queue.

•You should know your collections because they do save you time when used properly.•There are many collections to choose from.•You can build your own collections by implementing various interfaces.

However – We want Generics because we then can build

•Collections that are more type safe.•Collections that provide better performance – less boxing and unboxing.•Collections that are polymorphic in the elements they contain•The Framework contains a bunch of prefabricated Generics.

Page 25: Www.itu.dk Advanced C#, part I Niels Hallenberg IT University of Copenhagen BAAAP – Spring 2009.

www.itu.dk

GenericsClasses of System.Collections.Generic:

•Dictionary<TKey, TValue> : Generic collection of name / value pairs.

•List<T> : Resizable list of items.•Queue<T> : Standard FIFO queue•SortedDictionary<TKey, TValue> : Sorted

list of name / value pairs.•Stack<T> : Standard LIFO queue.

Page 26: Www.itu.dk Advanced C#, part I Niels Hallenberg IT University of Copenhagen BAAAP – Spring 2009.

www.itu.dk

Generics Example: Build a NameListMap that maps string values to a

list of arbitrary typed values T.

// Int listNameListMap<int> intMap = new NameListMap<int>();intMap.insert("A", 1);intMap.insert("A", 2);intMap.insert("B", 3);intMap.insert("B", 4);Console.WriteLine(intMap.pp());

// String listNameListMap<String> stringMap = new NameListMap<string>();stringMap.insert("A", "Hans");stringMap.insert("B", "Grethe");stringMap.insert("A", "Peter");stringMap.insert("B", "Kurt");Console.WriteLine(stringMap.pp());

{ (A [1,2]), (B [3,4])}

{ (A [Hans,Peter]), (B [Grethe,Kurt])}

Example: NameListMap

Page 27: Www.itu.dk Advanced C#, part I Niels Hallenberg IT University of Copenhagen BAAAP – Spring 2009.

www.itu.dk

Generics Example: Define the NameListMap class and implement the

map using a Dictionary.

internal class NameListMap<T> { private Dictionary<String, List<T>> map; internal NameListMap() { map = new Dictionary<string, List<T>>(); } …}

The type of elements in the list.

Create the dictionary

internal bool exists(String name) { return map.ContainsKey(name);}

It is easy to check if a name is already in the map.

Page 28: Www.itu.dk Advanced C#, part I Niels Hallenberg IT University of Copenhagen BAAAP – Spring 2009.

www.itu.dk

Generics Example: When inserting, we have to check if a key (name)

already exists and add the value element to the list.

If not a new list is created.

internal void insert(String name, T t) { List<T> ls; if (map.TryGetValue(name, out ls)) { ls.Add(t); map.Remove(name); map.Add(name, ls); } else { ls = new List<T>(); ls.Add(t); map.Add(name, ls); }}

Value name exists in the map.

Value name does not exists and a new list is created.

Page 29: Www.itu.dk Advanced C#, part I Niels Hallenberg IT University of Copenhagen BAAAP – Spring 2009.

www.itu.dk

Generics Example:

Lookup will return the entire list of values for the given name.

internal List<T> lookup(String name) { List<T> elem = default(List<T>); map.TryGetValue(name, out elem); return elem;}

Use default to initiate an ”empty” element.

Page 30: Www.itu.dk Advanced C#, part I Niels Hallenberg IT University of Copenhagen BAAAP – Spring 2009.

www.itu.dk

Delegate and Lambda

•Type safe function pointer•Must be fully applied•Annonymous methods can be declared on the fly•They inherit scope where they are declared.•A lambda is mostly syntactic sugar for anonymous delegates•Lambda:

(<parameters>) => { <implementation>}

•Type check (int i, String s) and Type inference (i, s).•Short notation for one-liners

Page 31: Www.itu.dk Advanced C#, part I Niels Hallenberg IT University of Copenhagen BAAAP – Spring 2009.

www.itu.dk

Delegate Example

List<int> l1 = new List<int>(new int[] { 1, 2, 3, 4 });printIntList("Before increment:", l1);

public static void printIntList(String msg, List<int> map) { List<String> xs = new List<string>(); foreach (int x in map) xs.Add(x.ToString()); Console.WriteLine( msg + " [" + String.Join(",", xs.ToArray()) + "]");}

This is really a stupid example, sorry

We define a delegate type and a simple delegate

public delegate RT FuncRT<T0, RT>(T0 a0);

public static FuncRT<int, int> incByOne = delegate(int x) { return x + 1; };

Page 32: Www.itu.dk Advanced C#, part I Niels Hallenberg IT University of Copenhagen BAAAP – Spring 2009.

www.itu.dk

Delegate Example

public static List<int> intListMap(List<int> map,FuncRT<int,int> fn) { List<int> map2 = new List<int>(); foreach (int x in map) map2.Add(fn(x)); return map2;}

We make a simple method, that can apply a delegate of type FuncRT<int,int> on a list of integers.

Use the intListMap method on the incOne delegate

List<int> l2 = intListMap(l1, incByOne);printIntList("After increment by 1:", l2);

// Add all elements by one - anonymous delegateList<int> l4 = intListMap(l1,delegate (int x) {return x+1;});printIntList("After increment by 1 (anon):", l4);

Page 33: Www.itu.dk Advanced C#, part I Niels Hallenberg IT University of Copenhagen BAAAP – Spring 2009.

www.itu.dk

Delegate Example

// Generate delegate that increments by Xpublic static FuncRT<int, int> genIncByX(int x) { return delegate(int y) { return y + x; };}

A method can also return a delegate. The parameter x is in scope of the delegate.

Generate a delegate that increments with 5.

List<int> l3 = intListMap(l1, genIncByX(5));printIntList("After increment by 5:", l3);

Add elements by one with anonymous delegate.

List<int> l4 = intListMap(l1,delegate (int x) {return x+1;});printIntList("After increment by 1 (anon):", l4);

Page 34: Www.itu.dk Advanced C#, part I Niels Hallenberg IT University of Copenhagen BAAAP – Spring 2009.

www.itu.dk

Lambda Example

List<int> l5 = intListMap(l1, (int x) => { return x + 1; });printIntList("After increment by 1 (anon, lambda 1):", l5);

The same examples using lambdas.

The lambda can access variables in scope.

int v = 42; // v is in scope.List<int> l6 = intListMap(l1, x => x + v);printIntList("After increment by 1 (anon, lambda v=42):", l6);

Using a named lambda

public static FuncRT<int, int> incByTwo = x => x + 2;

List<int> l7 = intListMap(l1, incByTwo);printIntList("After increment by 2 (named lambda):", l7);

Page 35: Www.itu.dk Advanced C#, part I Niels Hallenberg IT University of Copenhagen BAAAP – Spring 2009.

www.itu.dk

Test Data

You can use the access implementation of the Hotel Reception system.

– Table tblGuest contains 83 guests with real names– Given real guest names you can calculate test data by

some stochastic rules. For instance, you want 80% occupied rooms in January, 40% in February etc.

– If you calculate ahead you should be able to have some interesting test cases, eg., the search agent should also search in periods where all rooms are occupied.

– You can also calculate services received etc.– You should parameterize your program to generate hotels

of different occupation.

Page 36: Www.itu.dk Advanced C#, part I Niels Hallenberg IT University of Copenhagen BAAAP – Spring 2009.

www.itu.dk

Stubs

A Web service stub is basically an “empty” implementation of the service that fulfills the web service signature.

You can make stubs static so that they always return the same value or dynamic so that they return what seems to be different values.

If you make it dynamic, then try to have it return values that are good test cases.

Page 37: Www.itu.dk Advanced C#, part I Niels Hallenberg IT University of Copenhagen BAAAP – Spring 2009.

www.itu.dk

Assignments1. Make the Vechicle class implement ICloneable using deep

cloning. Use example SingleHeirarkyInterface.

2. Make the Vechicle class implement ICompareable comparing on the field vechicleName. Use example SingleHeirarkyInterface.

3. Implement a Ping service on hotel.itu.dk4. Define a BinaryOp delegate type that operates on two integer

values, eg plus, minus, multiplication and returns an integer.Make a method applyOp that takes two integer arguments and a BinaryOp delegate type and applies the delegate on the two parameters.

Mail your solutions to [email protected].

Page 38: Www.itu.dk Advanced C#, part I Niels Hallenberg IT University of Copenhagen BAAAP – Spring 2009.

www.itu.dk

Group Meetings Friday February 131. We all meet at 09.15 (I go by train)2. Group 1: 09.30 – 09.503. Group 2: 09.50 – 10.104. Group 3: 10.10 – 10.305. Group 4: 10.30 – 10.506. Group 5: 10.50 – 11.107. Group 6: 11.10 – 11.30