|
|
YOUR FEEDBACK
|
TOP MICROSOFT .NET LINKS Feature
DNDJ Feature — Introducing C# Generics
Leverage code reuse without sacrificing type safety
By: Robert R. Hauser
Nov. 5, 2006 12:00 PM
Digg This!
Page 2 of 3
« previous page
next page »
Reusing Code with Generics
public class List3<T> With the syntax <T> immediately after the class name, we indicate a type parameter, T, which stands in place of some actual type that's specified at each location where a new List3 is used. In fact, we won't call this class List3 but rather List3<T>. Within the class itself the type parameter T is used as if it were a real type (like our old String or Object types). The C# build time and runtime will conspire to use this generic class, List3<T>, as a template that can be used to generate as many "regular" classes as needed for each actual type that a program specifies to take the place of the type parameter T. Here's how Evan can refactor the string manipulation code to use the generic class List3<T>.
List3<String> aList = new List3<String>(); Note that where we want to use List3<T> we must specify what the type parameter really is - in this case String. The C# runtime will create a class for List3<String>, unless it's already done so. You don't need explicit casting because the Remove() method for List3<String> returns a String. At build time we have the advantage of full type checking that prevents entering the wrong type of object into the collection. Where the same code could operate identically on many types, using generics elegantly solves the tension of how to write reusable code while maintaining type safety.
Back to the Bakery
List3<BakeItem> waitingForOven = new List3<BakeItem>(); With three collections the software is modeling the process as bakery items are queued for the oven, cooked, and then put on display. To facilitate some cooking experiments, the baker asks Evan to track how many of a particular bakery item were in the oven at the same time. Each bakery item should maintain the maximum and minimum number of items in the oven during its cook time. First, Evan creates an IWatermark interface and implements that interface in the BakeItem class. The IWatermark interface is as follows and the BakeItem class that implements this interface is shown in Listing 3.
public interface IWatermark The bakery items that are in the oven are in a List3<BakeItem> collection in a variable called inOven. If this collection knew that it held items that implement the IWatermark interface then it could invoke the required instrumentation during the additions and removals of items in the collection. Having looked at the documentation for C# generics, Evan considers placing a constraint on a generic parameter type. Evan considers turning List3<T> into an intrusive container that makes use of the properties available via IWatermark. It would look like this: public class List3<T> where T : Iwatermark However, this would require implementing IWatermark on all of the classes List3<T> contains, including Customer types and String types. This would also prevent List3<T> from using primitive types. A more viable approach could be to alter List3<T> to test internally if the type that it holds implements IWatermark and if so then record the necessary statistics. We could make use of C#'s is operator in the implementation of List3<T> to test type compatibility dynamically for any T with IWatermark as follows:
public virtual void Add(T obj) Unfortunately this approach is undesirable. It adds useless code in the general case where List3<T> is used with a type that doesn't implement IWatermark. Another pitfall of this approach is that any object that implements IWatermark will be instrumented in any List3<T> that it's put in, not just the collection that's being used to represent the oven. Finally, this strategy hides the intrusive nature of List3<T> and thus can hide type mismatch errors. Leaving the List3<T> as general as possible, Evan implements List4<T> with a constraint that it requires anything put in it to implement IWatermark. See Listing 4 for the full watermarking collection. Here's the first line: public class List4<T> : List3<T> where T : Iwatermark A generic class can be used as a base class so Evan chose to specialize List4<T> from List3<T> but added a constraint that List4<T> requires all items put in it to implement IWatermark. The generic class List4<T> is explicit about its intrusive nature on the objects it holds and C#'s type safety provisions come into play at build time and runtime to prevent it from operating on inappropriate types. Here's the modified code snippet:
List3<BakeItem> waitingForOven = new List3<BakeItem>();
Delving Deeper C# allows for generic classes, structs, interfaces, delegates, static methods, and instance methods. Any of these can be parameterized based on type and we're not limited to a single type parameter. For example, we could have a generic class Several<T, U, V> where each type parameter could be the same or unrelated. Several<int, int, String> a = new Several<int, int, String>(); You can use generic methods to define algorithms that are clearly separated from the data type on which they operate. A generic method specifies type parameters following the method name: public U DoSomething<U, V>(U u, V v) Both parameters and return type can be made generic and the type parameters don't have to be the same as type parameters on the class. The C# compiler can do type inferencing on method parameters so that, for the above method, instead of coding DoSomething<String, int>("name", 2) you can simply type DoSomething("name", 2). The compiler infers the generic type parameters from the data types of the method parameters. Properties and indexers don't allow for introducing new type parameters but they can use any type parameters of the class that contains them. Generic methods support constraints on their type parameters like classes. Page 2 of 3 « previous page next page » MICROSOFT .NET LATEST STORIES
SUBSCRIBE TO THE WORLD'S MOST POWERFUL NEWSLETTERS SUBSCRIBE TO OUR RSS FEEDS & GET YOUR SYS-CON NEWS LIVE!
|
SYS-CON FEATURED WHITEPAPERS MOST READ THIS WEEK BREAKING NEWS FROM THE WIRES
|
||||||||||||||||||||||||||||||||||