10266A_12.ppt
- Количество слайдов: 33
Module 12 Using Collections and Building Generic Types
Module Overview • Using Collections • Creating and Using Generic Types • Defining Generic Interfaces and Understanding Variance • Using Generic Methods and Delegates
Lesson 1: Using Collections • What Is a Collection? • Using Collection Classes • Iterating Through a Collection • Common Collection Classes • Using Collection Initializers • Demonstration: Using Collections
What Is a Collection? int 4 string “Rich” int 5 int 4 Add: bool true string “Rich” int 5 int 4 Remove: int 5 string “Rich” bool true • Items in a collection are referenced by using the System. Object type • Collections manage space automatically
Using Collection Classes ICollection interface: IList interface: Copy. To Add Get. Enumerator Remove Count Implemented by all collection Implemented by some collection classes Items are stored in collections as Array. List list = new Array. List(); list. Add(6); objects. You must cast items retrieved from the collection Some collection classes use alternatives such as Push and Pop instead of Add and Remove list. Remove(6); list. Remove. At(1); int temp = (int)list[0]);
Iterating Through a Collection A foreach loop displays every item in a collection in turn foreach(<type> <control_variable> in <collection>) { <foreach_statement_body> } To use a foreach loop, the collection must expose an enumerator. The ICollection interface defines a Get. Enumerator method Array. List list = new Array. List(); list. Add(99); list. Add(10001); list. Add(25); . . . foreach (int i in list) { Console. Write. Line(i); } // Output: 99 // 10001 // 25
Common Collection Classes Array. List An unordered collection, similar to an array. Items are accessed by index Queue A first-in, first-out collection. Use the Enqueue method instead of Add Stack A first-in, last-out collection. Use the Push method instead of Add Hashtable A collection of key and value pairs. Suitable for large collections Sorted. List A collection of key and value pairs. Items are ordered based on the key
Using Collection Initializers You can use the Add method to add items to a collection Array. List al = new Array. List(); al. Add("Value"); al. Add("Another Value"); You can also use a collection initializer to add items to a collection when you define the collection // Assume person 1 and person 2 are instantiated // Person objects. Array. List al 2 = new Array. List() { person 1, person 2 }; You can combine collection initializers with object initializers Array. List al 3 = new Array. List() { new Person() {Name="James", Age =45}, new Person() {Name="Tom", Age =31} };
Demonstration: Using Collections In this demonstration, you will see how to: • Use a Sorted. List class to store a collection of Person objects by using the name property as the key • Access a Person object by using the name of the Person to retrieve the object from the collection • Add a Person object to a Queue collection class by using a collection initializer • Retrieve an object from a Queue collection
Lab A: Using Collections • Exercise 1: Optimizing a Method by Caching Data Logon information Virtual machine 10266 A-GEN-DEV User name Student Password Pa$$w 0 rd Estimated time: 20 minutes
Lab Scenario
Lab Review Questions • What namespace did you need to bring into scope before you could use the Hashtable class? • In the lab, you used a very simple hash to add items to the Hashtable object. How could you create a more complex hash?
Lesson 2: Creating and Using Generic Types • What Are Generic Types? • Compiling Generic Types and Type Safety • Defining a Custom Generic Type • Adding Constraints to Generic Types • Demonstration: Defining a Generic Type
What Are Generic Types? A generic type is a type that specifies one or more type parameters Type parameters are like other parameters except that they represent a type, not an instance of a type Type parameters are defined by using angle brackets after the class name public class List<T> This code example shows the definition of a class named List that takes a single type parameter named T. You can use T like any other type in the class
Compiling Generic Types and Type Safety The List<T> class is used several times with different type parameters List<string> names = new List<string>(); names. Add("John"); . . . string name = names[0]; List<string>> list. Of. Lists = new List<string>>(); list. Of. Lists. Add(names); . . . List<string> data = list. Of. Lists[0]; The compiler generates a strongly typed equivalent of the generic class, effectively generating the following methods public void Add(string item). . . public void Add(List<string> item) The compiler-generated classes and methods are generated when your application is compiled. You cannot call the strongly typed version directly
Defining a Custom Generic Type Define a class and specify a type parameter in angle brackets after the class name class Printable. Collection<TItem> { TItem [] data; int index; . . . public void Insert(TItem item) {. . . data[index] = item; . . . } } Use the type parameter as an alias You can also use the type for the type in fields and properties parameter in methods
Adding Constraints to Generic Types Constraint where T: struct Description The type argument must be a value type where T : class The type argument must be a reference type where T : new() The type argument must have a public default constructor where T : <base class name> The type argument must be, or derive from, the specified base class where T : <interface name> The type argument must be, or implement, the specified interface where T : U The type argument that is supplied for T must be, or derive from, the argument that is supplied for U
Demonstration: Defining a Generic Type In this demonstration, you will see how to: • Define a generic type • Use the generic type in a simple application
Lesson 3: Defining Generic Interfaces and Understanding Variance • Defining Generic Interfaces • What Is Invariance? • Defining and Implementing a Covariant Interface • Defining and Implementing a Contravariant Interface
Defining Generic Interfaces Generic interface with type parameters Generic class that implements the generic interface IPrinter<Document. Type> where Document. Type : IPrintable { void Print. Document(Document. Type Document); Print. Preview. Document(Document. Type Document) } class Printer<Document. Type> : IPrintable<Document. Type> where Document. Type : IPrintable { public void Print. Document(Document. Type Document) { // Send document to printer. Print. Service. Print((IPrintable)Document); } public Print. Preview. Document(Document. Type Document) { // Return a new Print. Preview object. return new Print. Preview((IPrintable)Document); } }
What Is Invariance? Invariance prevents you from casting type parameters with other types in the inheritance hierarchy IGeneric. Interface<string> cannot be cast to IGeneric. Interface<Object> despite being in the same inheritance hierarchy Without invariance, you could cast a string to an object. If the string is used as a method parameter, the code may throw exceptions Generic interfaces are invariant by default; generic classes are always invariant Invariant interfaces can be inflexible; covariance and contravariance can be used for appropriate type parameters
Defining and Implementing a Covariant Interface You can specify the out keyword with a type parameter in a generic interface if the type parameter is only ever used as a return type interface IRetrieve. Wrapper<out T> { T Get. Data(); } Using covariance, you can perform the following cast // Wrapper implements IRetrieve. Wrapper<string> string. Wrapper = new Wrapper<string>; // Without covariance this code would not be legal. // All strings are objects so a method which returns a string also returns an object. IRetrieve. Wrapper<object> object. Wrapper =string. Wrapper;
Defining and Implementing a Contravariant Interface You can specify the in keyword with a type parameter in a generic interface if the type parameter is only ever used as a method parameter type interface ISet. Wrapper<in T> { void Set. Data(T item); } Using contravariance, you can perform the following cast // Wrapper implements ISet. Wrapper<object> object. Wrapper = new Wrapper<object>; // Without contravariance this code would not be legal. // All strings are objects so a method which accepts an object can also accept a string. ISet. Wrapper<string> string. Wrapper = object. Wrapper;
Lesson 4: Using Generic Methods and Delegates • What Are Generic Methods and Delegates? • Using the Generic Delegate Types Included in the. NET Framework • Defining a Generic Method • Using Generic Methods • Demonstration: Defining a Generic Delegate
What Are Generic Methods and Delegates? void Add. To. Queue(Report report) { print. Queue. Add(report); } void Add. To. Queue(Reference. Guide reference. Guide) { print. Queue. Add(reference. Guide); } Instead of duplicating methods with different parameters, you can use a generic method with a type parameter void Add. To. Queue<Document. Type>(Document. Type document) { print. Queue. Add(report); } delegate void Print. Document. Delegate<Document. Type>(Document. Type document);
Using the Generic Delegate Types Included in the . NET Framework Action<T> You can use the Action delegate instead of declaring custom delegates for methods with no return type Func<T, TResult> You can use the Action delegate instead of declaring custom delegates for methods with a return type. The TResult type parameter represents the return type and is always the last type parameter The. NET Framework 4 includes overloads of both the Action and Func delegates for up to 16 input parameters
Defining a Generic Method Define a method and specify a type parameter (or several) in angle brackets after the method name Result. Type My. Method<Parameter 1 Type, Result. Type>(Parameter 1 Type param 1) where Result. Type : new() { Result. Type result = new Result. Type(); return result; } Specify any constraints on the type parameters Use the type parameter(s) in the method parameters, return type, and method body
Using Generic Methods To invoke a generic method, specify the type parameter T Perform. Update<T>(T input) { T output = // Update parameter. return output; }. . . string result = Perform. Update<string>("Test"); int result 2 = Perform. Update<int>(1); If you invoke a generic method, the compiler generates a concrete method for each invocation string Perform. Update(string input) // You cannot call this method. { string output = // Update parameter. return output; } int Perform. Update(int input) // You cannot call this method. { int output = // Update parameter. return output; }
Demonstration: Defining a Generic Delegate In this demonstration, you will see how to: • Define a custom generic delegate • Create an instance of the generic delegate • Create an instance of a generic delegate by using the Action generic delegate type • Invoke the custom generic delegate instance and the Action generic delegate instance
Lab B: Building Generic Types • Exercise 1: Defining a Generic Interface • Exercise 2: Implementing a Generic Interface • Exercise 3: Implementing a Test Harness for the Binary. Tree Project • Exercise 4: Implementing a Generic Method Logon information Virtual machine 10266 A-GEN-DEV User name Student Password Pa$$w 0 rd Estimated time: 40 minutes
Lab Scenario
Lab Review Questions • In the lab, you defined a generic interface with a type parameter. How did you constrain the types that can be used with a class that implements this interface? • In the lab, you used the name TItem for the type parameter of the Tree class, and the name Tree. Item for the static generic method in the class. Why did you not use the same name in both instances?
Module Review and Takeaways • Review Questions • Best Practices
10266A_12.ppt