|
|
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 1 of 3
next page »
How often have you wanted to reuse some code you previously wrote but it didn't quite fit in your current project? Code reuse is an oft-touted benefit of modern object-oriented programming. With the advent of generic support in the C# language appearing in the .NET Framework 2.0 developers have new leverage for writing code that can be reused without compromising type safety.
Object a = new Object(); The second line will generate a compiler error because a plain Object can't be used as a String while maintaining type safety. Unfortunately, build-time type checking is ineffective if explicit casts are used. A cast lets the programmer circumvent the type checking at build time. For programming languages without runtime type checking this can result in invalid operations on data types having unpredictable consequences, such as manipulating a fragment of a String data type as if it were an int. C# provides type safety checks at runtime as well as build time. Here is a type mismatch error that won't be caught until the program is run:
Object a = new Object(); The program will build without errors. However, when running the program, it will generate an InvalidCastException on the second line because the Object referred to by 'a' can't be converted to the type String. This type mismatch error is blatant but serves to remind us to avoid explicit casting since it negates the type safety provided at build time. Relegating these errors to program runtime incurs additional productivity cost (See "The Zen of Strong Typing" sidebar). In fact, now that we have the flavor of the type checking performed at build time, languages providing type safety features shouldn't lead us into situations that require us to turn off type safety by introducing such casts.
Reusing Code Without Generics Now Evan can use the collection as follows:
List1 aList = new List1(); List1 is type safe, meaning it accepts and returns String types and this type safety is enforced at build time. Eventually Evan has to track the products waiting for the oven, items in the oven, and goods under the display counter. This is an opportunity for reusing the previously programmed collection, List1. The problem is he now needs to collect BakeItems, not Strings. Evan could copy the source code to form a new collection by replacing String with BakeItem, but this approach has dire consequences. If an error is found later then both copies of the source code will have to be fixed. The baker has also indicated that Evan will also have to track waiting customers, inventory shipments, and other things. Writing separate collection code for each data type is clearly not desirable. Evan decided to rewrite the collection with the most generally available type, Object. This results in a List2 class where the only difference is the replacement of all uses of the data type String with Object noted in bold text. Below is a fragment of List2.
public class List2 Deprecating List1 in favor of List2 requires refactoring the earlier string collecting code.
List2 aList = new List2(); The advantage of this rewrite is that we can use List2 for any type of thing we want to collect. For primitive types, C# will perform a conversion to an appropriate object in a process called boxing. This lets us transparently handle primitive types as if they were objects. Therefore, we could use List2 with int as follows:
aList.Add(1); For Evan, List2 seems well prepared for String, int, BakeItem, Customer, or anything else he might need. However, note that a cast is now necessary to convert from the most general type, Object, to the actual type, String or int in the code fragments. Recall that explicit casting is just the situation we want to avoid so we don't negate the type checking done at build time. For instance, during the development effort, Evan accidentally added an instance of a data type called BakeItem to a List2 collection meant only to contain Customer elements. The error will appear as an InvalidCastException at runtime, with no indication of problems at build time. This weakens the original intent of having multiple different homogenous collections in a way that allows any individual collection to accept unintended data types. Even with the explicit casts that negate build time type checking, this approach to reusing code is superior to the alternative of writing code for a multitude of type-specific collections. This code reuse versus type safety tension was a problematic state of affairs with C# 1.1. With the addition of generics to C# 2.0 there is now a better solution to hand. Page 1 of 3 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
|
||||||||||||||||||||||||||