YOUR FEEDBACK
Chris Keene's Prescription for Curing the Java Flu
Pedro wrote: "Adobe and Microsoft are doing a far better job making their ...

SYS-CON.TV
TOP MICROSOFT .NET LINKS


DNDJ Feature — Introducing C# Generics
Leverage code reuse without sacrificing type safety

Digg This!

Page 2 of 3   « previous page   next page »

Reusing Code with Generics
By using generics Evan can get the benefit of type safety at build time without having to duplicate code. Let's see how with a code fragment showing the major changes needed. The full code for generic List3<T> is found in Listing 2.

    public class List3<T>
    {
      internal static T NO_ITEM = default(T);
      internal class ListNode
      {
        public ListNode next = null;
        public T obj = NO_ITEM;
      }
      // ...

      public virtual void Add(T obj)
      // ...

      public virtual T Remove()
      // ...

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>();
    aList.Add("a");
    aList.Add("b");
    for (Object item = aList.Remove();
      item != List3<String>.NO_ITEM;
      item = aList.Remove())
    {
      // Do something with item
    }

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
Back at the bakery, Evan uses the generic List3<T> with Strings, Customer objects, and BakeItem objects:

    List3<BakeItem> waitingForOven = new List3<BakeItem>();
    List3<BakeItem> inOven = new List3<BakeItem>();
    List3<BakeItem> onDisplay = 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
    {
      int HighMark { get; set; }
      int LowMark { get; set; }
    }

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)
    {
      if (obj is IWatermark) {
        // Do stuff with IWatermark methods
    }

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>();
    List4<BakeItem> inOven = new List4<BakeItem>();
    List3<BakeItem> onDisplay = new List3<BakeItem>();

Delving Deeper
Through illustration we introduced generic classes and how to put a constraint on a generic type parameter.

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 »

About 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.

MICROSOFT .NET LATEST STORIES
Peer Networking Series - A Closer Look at PNRP vs. Bonjour/ZeroConf
It seems as though whenever I bring up PNRP and its benefits, I am immediately inundated with a list of questions or comments indicating that Microsoft is re-inventing the wheel and that PNRP has already been implemented before in the form of ZeroConf and, more specifically, Apple's im
db4o Open Source Object-Oriented Database Supports LINQ
db4objects has announced that its db4o object database is now optimized for Microsoft's LINQ. With the new support, developers can choose an object-oriented optimized engine without changing the API or compromising performance. db4object's db4o database offers a persistence solution to
Microsoft, Unisys, Yahoo and Vista
Microsoft, which spent $6 billion on aQuantive and was chasing Yahoo for its ads before it came to a dead stop, has been supporting - as in helping write - legislation in New York and Connecticut that would regulate the data that companies like Yahoo and Google collect for targeted adv
AJAX World - Xceed Launches Microsoft Silverlight 2 Control
Xceed launched Xceed Upload for Silverlight, the commercial offering in support of Microsoft's promising new Silverlight technology. The product is available now for purchase or as a fully functional 45-day trial on Xceed's website. Xceed Upload for Silverlight lets developers add uplo
Microsoft To Keynote 4th International Virtualization Conference & Expo
Mike Neil is general manager for virtualization strategy in the Windows Server Division at Microsoft. Mike is focused on the delivery of the Windows virtualization technology, including Windows Server 2008 Hyper-V, Microsoft Hyper-V Server and Virtual PC 2007. Mike also directs the tec
SUBSCRIBE TO THE WORLD'S MOST POWERFUL NEWSLETTERS
SUBSCRIBE TO OUR RSS FEEDS & GET YOUR SYS-CON NEWS LIVE!
Click to Add our RSS Feeds to the Service of Your Choice:
Google Reader or Homepage Add to My Yahoo! Subscribe with Bloglines Subscribe in NewsGator Online
myFeedster Add to My AOL Subscribe in Rojo Add 'Hugg' to Newsburst from CNET News.com Kinja Digest View Additional SYS-CON Feeds
Publish Your Article! Please send it to editorial(at)sys-con.com!

Advertise on this site! Contact advertising(at)sys-con.com! 201 802-3021

SYS-CON FEATURED WHITEPAPERS

ADS BY GOOGLE
BREAKING NEWS FROM THE WIRES
High Growth Forecasted for the Mobile search 2008-2013: Profiting From Information and Advertising on the Move
Reportlinker.com announces that a new market research report related to the Wireless industr