| By Robert R. Hauser | Article Rating: |
|
| November 5, 2006 12:00 PM EST | Reads: |
14,818 |
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.
About Type Safety
A key benefit to languages that support type checking is type safety. Type safety at build time and/or runtime prevents code from manipulating data of an incorrect type. As part of its type safe approach, C# detects type mismatch errors at build time in the compiler and at runtime in the Common Language Runtime (CLR). The following is a type mismatch error that C# will catch at build time:
Object a = new Object();
String b = a;
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();
String b = (String)a;
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
Evan, a programmer hired to write software for a local bakery, needs to manipulate strings. The implementation of a minimal collection is shown in Listing 1. The collection is a singly linked list called List1. Since Evan is only interested in storing String type data at this point, he builds the collection to fit the need to store String data. The bold text in Listing 1 shows the locations where the collection is specific to the type String.
Now Evan can use the collection as follows:
List1 aList = new List1();
aList.Add("a");
aList.Add("b");
for (String item = aList.Remove();
item != List1.NO_ITEM;
item = aList.Remove())
{
// Do something with item
}
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
{
public static Object NO_ITEM = default(Object);
internal class ListNode
{
public ListNode next = null;
public Object obj = NO_ITEM;
}
// ...
public virtual void Add(Object obj)
// ...
public virtual Object Remove()
// ...
Deprecating List1 in favor of List2 requires refactoring the earlier string collecting code.
List2 aList = new List2();
aList.Add("a");
aList.Add("b");
for (Object item = aList.Remove();
item != List2.NO_ITEM;
item = aList.Remove())
{
String theValue = (String)item;
// Do something with theValue
}
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);
aList.Add(2);
for (Object item = aList.Remove();
item != List2.NO_ITEM;
item = aList.Remove())
{
int theValue = (int)item;
// Do something with theValue
}
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.
Published November 5, 2006 Reads 14,818
Copyright © 2006 SYS-CON Media, Inc. — All Rights Reserved.
Syndicated stories and blog feeds, all rights reserved by the author.
More Stories By Robert R. Hauser
Robert R. Hauser has a masters degree in computer science specializing in Artificial Intelligence with more than 15 years of development experience in C, C++, C#, and Java, building software for networking, filesystems, middleware, and natural language processing. He works at Recursion Software, which is focused on providing a next generation application platform for .NET and Java.
- The Importance of Abstraction in Cloud Computing
- Whatever the Apple iPad Is, It Apparently Leaks Like a Sieve
- Reality Check at the Cloud Expo
- Microsoft’s First Step Toward Cloud Computing
- Six Enterprise Megatrends to Watch in 2010
- Economy Drives Adoption of Virtual Lab Technology
- My Personal 2010 Predictions
- How PowerBuilder Got Its Groove Back
- Cloud Computing Was the Big News of 2009
- Adaptivity “Platinum Plus Sponsor” of Cloud Expo
- UPDATE: Adobe & IE Implicated as China’s Spy Holes
- Top Ten Reasons To Use "Real" Outlook On Your iPhone
- Kindle 2 vs Nook
- Cloud Expo New York Call for Papers Now Open
- The Importance of Abstraction in Cloud Computing
- Whatever the Apple iPad Is, It Apparently Leaks Like a Sieve
- Reality Check at the Cloud Expo
- Tactical Cloud Computing Panel at 1st Annual GovIT Expo
- Microsoft’s First Step Toward Cloud Computing
- Six Enterprise Megatrends to Watch in 2010
- Economy Drives Adoption of Virtual Lab Technology
- My Personal 2010 Predictions
- How PowerBuilder Got Its Groove Back
- Cloud Computing Was the Big News of 2009
- Google Maps and ASP.NET
- Crystal Reports XI & How It Has Changed
- Converting VB6 to VB.NET, Part I
- Creating Controls for.NET Compact Framework in Visual Studio 2005
- Where Are RIA Technologies Headed in 2008?
- How to Write High-Performance C# Code
- AJAX World RIA Conference & Expo Kicks Off in New York City
- Implementing Tab Navigation with ASP.NET 2.0
- i-Technology Photo Exclusive: Bill Gates & Steve Jobs In "Nerds"
- .NET Archives: Getting Reacquainted with the Father of C#
- Programmatically Posting Data to ASP .NET Web Applications
- i-Technology Viewpoint: "SOA Sucks"






















