Download Understanding Collection Classes, Generics, Delegates, Events and Lambda Expressions in C# and more Lecture notes Introduction to Computing in PDF only on Docsity!
Session 3
Chapter 9, 10 – Collections and
Generics, Delegate, Events, and
Lambda Expression
Outline
• Collection classes
• Problems of Nongeneric
• The Role of Generic Type Parameters
• The System.Collection.Generic Namespace
• Delegate types
• Understanding events
• Understanding Anonymous Methods
• Understanding Lambda Expressions
The Motivation for Collection Classes
- (^) The array
- (^) The most primitive container you could use to hold application data
- (^) Basic arrays can be useful to manage small amounts of fixed-size
data
- (^) There are many other times where you require a more flexible data structure - (^) E.g., a dynamically growing and shrinking container
- (^) .NET base class libraries provide number of collection classes
- (^) To dynamically resize themselves on the fly as you insert or remove
items
- (^) Offer increased type safety and are highly optimized to process
The Motivation for Collection Classes
- (^) A collection class can belong to one of two broad categories - (^) Nongeneric collections (primarily found in the System.Collections namespace) - (^) Generic collections (primarily found in the System.Collections.Generic namespace)
- (^) Nongeneric collections
- (^) Operate on System.Object types and are, therefore, loosely typed containers
- (^) Generic collections are much more type safe
- (^) You must specify the "type of type" they contain upon creation
Working with the ArrayList
using System;
using System.Collections;
namespaceTestCode
class MainClass
public static void Main(string[] args)
ArrayList strArray =new ArrayList();
strArray.AddRange(new string[] {"First", "Second", "Third" });
// Show number of items in ArrayList.
Console.WriteLine("This collection has { 0 }items.", strArray.Count);
Console.WriteLine();
// Add a new item and display current count.
strArray.Add( 4 ); // Nongeneric =>not typesafe.
Console.WriteLine("This collection has { 0 }items.", strArray.Count);
// Display contents.
foreach (string s in strArray)
Console.WriteLine("Entry: {0}", s);
Console.WriteLine();
The Problems of Nongeneric Collections
- (^) First, poorly performing code
- (^) Especially when you are manipulating numerical data
- (^) CLR must perform a number of memory transfer operations when you store structures in any nongeneric collection class prototyped to operate on System.Objects
- (^) Second, not type safe
- (^) Because they were developed to operate on System.Objects
- (^) User needs to cast to specific type to use, this might lead to wrong type casting
The System.Collections.Generic Namespace
Person.cs
public class Person
public string FirstName{get;set;}
public string LastName{get;set;}
public int Age{get;set;}
public Person()
public Person(string firstName, string lastName, int age)
FirstName=firstName;
LastName=lastName;
Age=age;
public overridestring ToString()
return string.Format("{0}{ 1 }, {2}", FirstName, LastName, Age);
Working with the Stack Class
public static void Main(string[] args) { StackstackOfPeople=new Stack(); stackOfPeople.Push(new Person {FirstName ="Homer", LastName="Simpson", Age= 47 }); stackOfPeople.Push(new Person {FirstName ="Marge", LastName ="Simpson", Age= 45 }); stackOfPeople.Push(new Person {FirstName ="Lisa", LastName="Simpson", Age= 9 }); // Now look at thetop item, pop it, and look again. Console.WriteLine("First person is: { 0 }", stackOfPeople.Peek()); Console.WriteLine("Popped off { 0 }", stackOfPeople.Pop()); Console.WriteLine("\nFirst person is: {0}", stackOfPeople.Peek()); Console.WriteLine("Popped off { 0 }", stackOfPeople.Pop()); Console.WriteLine("\nFirst person item is: { 0 }", stackOfPeople.Peek()); Console.WriteLine("Popped off { 0 }", stackOfPeople.Pop()); try { Console.WriteLine("\nnFirst person is: { 0 }", stackOfPeople.Peek()); Console.WriteLine("Popped off { 0 }", stackOfPeople.Pop()); } catch (InvalidOperationException ex) { Console.WriteLine("\nError! { 0 }", ex.Message); } }
Working with the Queue Class
static void GetCoffe e(Person p) { Console.WriteLine("{ 0 }got coffe e!", p.FirstName); } public static void Main(string[] args) { // Makea Q with threepeople. QueuepeopleQ =new Queue(); peopleQ.Enqueue(new Person {FirstName="Homer", LastName="Simpson", Age= 47 }); peopleQ.Enqueue(new Person {FirstName="Marge", LastName="Simpson", Age = 45 }); peopleQ.Enqueue(new Person {FirstName="Lisa", LastName ="Simpson", Age= 9 }); // Peek at first person in Q. Console.WriteLine("{ 0 }is first in line!", peopleQ.Peek().FirstName); // Remove each person from Q. GetCoffe e(peopleQ.Dequeue()); GetCoffe e(peopleQ.Dequeue()); GetCoffe e(peopleQ.Dequeue()); // Try to de-Q again? try { GetCoffe e(peopleQ.Dequeue()); } catch (InvalidOperationException e) { Console.WriteLine("Error! { 0 }", e.Message); } }
Working with the SortedSet Class
public static void Main(string[] args) { // Makesomepeoplewith different ages. SortedSetsetOfPeople=new SortedSet(new SortPeopleByAge()) { new Person {FirstName="Homer", LastName="Simpson", Age= 47 }, new Person {FirstName="Marge", LastName="Simpson", Age= 45 }, new Person {FirstName="Lisa", LastName="Simpson", Age= 9 }, new Person {FirstName="Bart", LastName="Simpson", Age= 8 } }; // Note theitems aresorted by age! foreach (Person p in setOfPeople) { Console.WriteLine(p); } Console.WriteLine(); // Add a few new people, with various ages. setOfPeople.Add(new Person {FirstName="Saku", LastName="J ones", Age= 1 }); setOfPeople.Add(new Person {FirstName="Mikko", LastName="J ones", Age= 32 }); // Still sorted by age! foreach (Person p in setOfPeople) { Console.WriteLine(p); } }
Working with the Dictionary<TKey, TValue> Class
public static void Main(string[] args)
// Populateusing Add() method
Dictionary<string, Person>peopleA =new Dictionary<string, Person>();
peopleA.Add("Homer", new Person {FirstName="Homer", LastName="Simpson", Age= 47 });
peopleA.Add("Marge", new Person {FirstName="Marge", LastName="Simpson", Age= 45 });
peopleA.Add("Lisa", new Person {FirstName="Lisa", LastName="Simpson", Age= 9 });
// Get Homer.
Person homer =peopleA["Homer"];
Console.WriteLine(homer);
// Populatewith initialization syntax.
Dictionary<string, Person>peopleB =new Dictionary<string, Person>()
{"Homer", new Person {FirstName="Homer", LastName="Simpson", Age= 47 }},
{"Marge", new Person {FirstName="Marge", LastName="Simpson", Age= 45 }},
{"Lisa", new Person {FirstName="Lisa", LastName="Simpson", Age= 9 }}
// Get Lisa.
Person lisa =peopleB["Lisa"];
Console.WriteLine(lisa);
Understanding the .NET Delegate Type
- (^) Programmers use callbacks to configure one function to report back to another function in the application - (^) E.g., to handle button clicking, etc., and general bidirectional communications between two entities in memory
- (^) A delegate
- (^) Is a type-safe object that points to another method (or list of methods), which can be invoked at a later time
- (^) A delegate maintains three important pieces of information
- (^) The address of the method on which it makes calls
- (^) The parameters (if any) of this method
- (^) The return type (if any) of this method
Defining a Delegate Type in C#
• To create a delegate type in C#
– Use the delegate keyword
– The name can be whatever you desire
– However, you must define the delegate to match the
signature of the method(s) it will point to
• For example, the following delegate type can point
to any method that
– takes two integers as input parameters
– returns an integer
– public delegate int BinaryOp(int x, int y);