C#
  Home arrow C# arrow Page 4 - Generics
ASP Free Forums 
.NET  
ASP  
ASP Code  
ASP.NET  
ASP.NET Code  
BrainDump  
C#  
Code Examples  
Database  
Database Code  
IIS  
Microsoft Access  
MS SQL Server  
Silverlight  
Visual Basic.NET  
Windows Scripting  
Windows Security  
XML  
Mobile Linux 
App Generation ROI 
IBM® developerWorks 
ASP Web Hosting  
ASP.NET Web Hosting 
Windows Web Hosting
 
Weekly Newsletter
 
Developer Updates  
Free Website Content 
 RSS  Articles
 RSS  Forums
 RSS  All Feeds
Write For Us Get Paid 
Request Media Kit
Contact Us 
Site Map 
Privacy Policy 
Support 
 USERNAME
 
 PASSWORD
 
 
  >>> SIGN UP!  
  Lost Password? 
C#

Generics
By: O'Reilly Media
  • Search For More Articles!
  • Disclaimer
  • Author Terms
  • Rating: 5 stars5 stars5 stars5 stars5 stars / 2
    2008-12-11

    Table of Contents:
  • Generics
  • 4.2 Understanding Generic Types
  • 4.3 Replacing the ArrayList with Its Generic Counterpart
  • 4.4 Replacing the Stack and Queue with Their Generic Counterparts

  • Rate this Article: Poor Best 
      ADD THIS ARTICLE TO:
      Del.ici.ous Digg
      Blink Simpy
      Google Spurl
      Y! MyWeb Furl
    Email Me Similar Content When Posted
    Add Developer Shed Article Feed To Your Site
    Email Article To Friend
    Print Version Of Article
    PDF Version Of Article
     
     
    ADVERTISEMENT


    Generics - 4.4 Replacing the Stack and Queue with Their Generic Counterparts


    (Page 4 of 4 )

     

    Problem

    You want to enhance the performance of your application as well as make the code easier to work with by replacing all Stack and Queue objects with their generic versions. This is imperative when you find that structures or other value types are being stored in these data structures, resulting in boxing/unboxing operations.

    Solution

    Replace all occurrences of the System.Collections.Stack and System.Collection.Queue objects with the System.Collections.Generic.StackandSystem.Collection.Generic.Queueobjects.

    Here is a simple example of using aSystem.Collections.Queueobject:

      public static void UseNonGenericQueue()
     
    {
        
    // Create a non-generic Queue object.
        
    Queue numericQueue = new Queue();

         // Populate Queue (causing a boxing operation to occur).
         numericQueue.Enqueue(1);
         numericQueue.Enqueue(2);
         numericQueue.Enqueue(3);

         // De-populate Queue and display items (causing an unboxing operation to occur)
         Console.WriteLine(numericQueue.Dequeue());
        
    Console.WriteLine(numericQueue.Dequeue());
         Console.WriteLine(numericQueue.Dequeue().ToString());
      }

    Here is that same code using aSystem.Collections.Generic.Queueobject:

      public static void UseGenericQueue()
     
    {
         // Create a generic Queue object.
         Queue<int> numericQueue = new Queue<int>();

         // Populate Queue.
         numericQueue.Enqueue(1);
         numericQueue.Enqueue(2);
         numericQueue.Enqueue(3);

         // De-populate Queue and display items.
         Console.WriteLine(numericQueue.Dequeue());
         Console.WriteLine(numericQueue.Dequeue());
         Console.WriteLine(numericQueue.Dequeue());
     
    }

    Here is a simple example of using aSystem.Collections.Stackobject:

      public static void UseNonGenericStack()
      {
         // Create a non-generic Stack object.
         Stack numericStack = new Stack();

         // Populate Stack (causing a boxing operation to occur).
         numericStack.Push(1);
         numericStack.Push(2);
         numericStack.Push(3);

         // De-populate Stack and display items (causing an unboxing operation to
    occur).
         Console.WriteLine(numericStack.Pop().ToString());
         Console.WriteLine(numericStack.Pop().ToString());
         Console.WriteLine(numericStack.Pop().ToString());
      }

    Here is that same code using aSystem.Collections.Generic.Stackobject:

      public static void UseGenericStack()
     
    {
         // Create a generic Stack object.
         Stack<int> numericStack = new Stack<int>();

         // Populate Stack.
         numericStack.Push(1);
         numericStack.Push(2);
         numericStack.Push(3);

         // De-populate Stack and display items.
         Console.WriteLine(numericStack.Pop().ToString());
         Console.WriteLine(numericStack.Pop().ToString());
         Console.WriteLine(numericStack.Pop().ToString());
      }

    Discussion

    On the surface, the generic and nongeneric Queue and Stack classes seem similar enough. However, it is a very different story underneath the surface. The basic use of the generic Queue andStackobjects are the same as with their nongeneric counterparts, except for the syntax used to instantiate the objects. The generic form requires a type argument in order to create the type. The type argument in this example is anint. This type argument indicates that thisQueueorStackobject will be able to contain only integer types, as well as any type that implicitly converts to an integer, such as ashort:

      short s = 300;
     
    numericQueue.Enqueue(s);   // OK, because of the implicit conversion 

    However, a type that cannot be implicitly converted to an integer, such as adouble, will cause a compile-time error:

      double d = 300;
      numericQueue.Enqueue(d);        // Error, no implicit conversion available
      numericQueue.Enqueue((int)d);   // OK, because of the explicit cast

    The nongeneric form does not require this type argument, because the nongenericQueueandStack objects are allowed to contain any item as an element because all items are convertible to typeObject.

    When choosing between a generic and nongenericQueueorStack, you need to decide whether you wish to use a genericQueue orStackobject or a nongenericQueueorStack object. Choosing the genericQueueorStackclass over its nongeneric form gives you many benefits, including:

    Type-safety

    Each element contained in the data structure is typed to one specific type. This means no more casting of objects when they are added to or removed from the data structure. You cannot store multiple disparate types within a single data structure; you always know what type is stored within the data structure. Type checking is done at compile time rather than runtime. This boils down to writing less code, achieving better performance, and making fewer errors.

    Shortened development time

    To make a type-safe data structure without using generics means having to subclass theSystem.Collections.QueueorSystem.Collections.Stackclass in order to create your own. This is time-consuming and error-prone.

    Performance

    The genericQueue orStackdoes not require a cast that could fail to occur when adding and removing elements from it. In addition, no boxing operation occurs when adding a value type to theQueueorStack. Likewise, in almost all cases, no unboxing operation occurs when removing a value type from theQueueorStack.

    Easier-to-read code

    Your code base will be much smaller because you will not have to subclass the nongenericQueueorStackclass to create your own strongly typed class. In addition, the type-safety features of generic code will allow you to better understand what the purpose of theQueue orStackclass is in your code.

    The following class members are implemented in the nongenericQueueandStack classes but not in their generic counterparts:

      Clonemethod
      IsSynchronizedproperty
     SyncRootproperty
     Synchronizedmethod

    The addition of theClonemethod on the nongenericQueueandStackclasses is due to theICloneable interface being implemented only on the nongenericQueueandStackclasses. However, all other interfaces implemented by the generic and nongenericQueue andStack classes are identical.

    One way around the missingClonemethod in the genericQueue andStackclasses is to use the constructor that accepts anIEnumerable<T>type. Since this is one of the interfaces that theQueueandStackclasses implement, it is easy to write. For theQueueobject, the code is as follows:

      public static void CloneQueue()
     
    {
        
    // Create a generic Queue object.
        
    Queue<int> numericQueue = new Queue<int>();

         // Populate Queue.
        
    numericQueue.Enqueue(1);
        
    numericQueue.Enqueue(2);
        
    numericQueue.Enqueue(3);

         // Create a clone of the numericQueue.
         Queue<int> clonedNumericQueue = new Queue<int>(numericQueue);

         // This does a simple peek at the values, not a dequeue.
         foreach (int i in clonedNumericQueue)
         {
            Console.WriteLine("foreach: " + i.ToString());
         }

         // De-populate Queue and display items.
        
    Console.WriteLine(clonedNumericQueue.Dequeue().ToString());
        
    Console.WriteLine(clonedNumericQueue.Dequeue().ToString());
        
    Console.WriteLine(clonedNumericQueue.Dequeue().ToString());
      }

    The output for this method is shown here:

      foreach: 1
      foreach: 2
      foreach: 3
      1
      2
      3

    For theStackobject, the code is as follows:

      public static void CloneStack()
     
    {
         // Create a generic Stack object.
         Stack<int> numericStack = new Stack<int>();

         // Populate Stack.
         numericStack.Push(1);
         numericStack.Push(2);
         numericStack.Push(3);

         // Clone the numericStack object.
         Stack<int> clonedNumericStack = new Stack<int>(numericStack);

         // This does a simple peek at the values, not a pop.
         foreach (int i in clonedNumericStack)
         {
           
    Console.WriteLine("foreach: " + i.ToString());
         }

         // De-populate Stack and display items.
         Console.WriteLine(clonedNumericStack.Pop().ToString());
         Console.WriteLine(clonedNumericStack.Pop().ToString()); 
         Console.WriteLine(clonedNumericStack.Pop().ToString());
     
    }

    The output for this method is shown here:

      foreach: 1
      foreach: 2
      foreach: 3
      1
      2
      3

    This constructor creates a new instance of theQueue orStackclass containing the elements copied from theIEnumerable<T>type.

    See Also

    The “System.Collections.Stack Class,” “System.Collections.Generic.Stack Class,” “System.Collections.Queue Class,” and “System.Collections.Generic.Queue Class” topics in the MSDN documentation.

    Please check back next week for the continuation of this article.


    DISCLAIMER: The content provided in this article is not warranted or guaranteed by Developer Shed, Inc. The content provided is intended for entertainment and/or educational purposes in order to introduce to the reader key ideas, concepts, and/or product reviews. As such it is incumbent upon the reader to employ real-world tactics for security and implementation of best practices. We are not liable for any negative consequences that may result from implementing any information covered in our articles or tutorials. If this is a hardware review, it is not recommended to open and/or modify your hardware.

       · This article is an excerpt from the book "C# 3.0 Cookbook, Third Edition," published...
     

    Buy this book now. This article is excerpted from chapter four of the C# 3.0 Cookbook, Third Edition, written by Jay Hilyard and Stephen Teilhet (O'Reilly, 2008; ISBN: 059651610X). Check it out today at your favorite bookstore. Buy this book now.

    C# ARTICLES

    - Coding a CRC-Generating Algorithm in C
    - Cyclic Redundancy Check
    - Handling Methods and Functions
    - Destroying Objects in C#
    - Creating Objects in C-Sharp
    - Classes and Objects
    - Programming Languages: Managed versus Native
    - LINQ-to-MySQL with DbLinq in C#
    - Working with Dates and Times in C#
    - Generics, Dictionaries, and More
    - More About Generics
    - Working with C# Collections
    - Generics
    - C# and XML
    - Pointers and Arrays in C#





    © 2003-2009 by Developer Shed. All rights reserved. DS Cluster 5 Hosted by Hostway
    For more Enterprise Application Development news, visit eWeek