What are C# Generics - Part II

by agrace 11. April 2008 20:49

Generics I'm going to keep this as simple as possible. Your main goal is to gain an appreciation of why we would want to use generics in the first place. The typical candidate scenario for the use of generics is where we have a class that has a member variable, and the type of this variable should be defined by the client of the class, and not by the programmer. Likewise, for a method that has a parameter passed to it. In other words, the code in our classes and methods remains the same and the types of the data can change with each use. Think code reuse.

Up to now, this type of generality involved writing the same code over and over for each type you wanted to accomodate. And with collections, you would typically have to use the object class and then cast back. This would involve boxing and unboxing for value types, which would incur heavy performance hits, depending on the size of your collections. More importantly, when casting back, you could not be certain of the type in the collection. This could result in runtime errors after your code had shipped. More than anything else, the type safety afforded by generics is its biggest selling point. Type-safe code is the easiest code to maintain, plain and simple.

With generics, we declare type-parameterized code which we can instantiate with different types. We write the code with '<T>' placeholders for types and then plug in the actual types when we are creating an instance. We don't have to use the letter 'T', it's just convention.

// 1.1 Loosely-Typed Collection
Class Stack
  public object Pop();

Stack s = new Stack();

// Cast necessary
int i = (int) s.Pop();


// 2.0 Strongly-Typed Collection
Class Stack<T>
  public <T> Pop();

Stack<int> s = new Stack<T>();

// No cast necessary
int i = s.Pop();


You'll probably find the most ready use for generics when implementing collections. The generic collection classes are part of the C# 2.0 System.Collections.Generic namespace. Below is a list of the traditional 1.1 collections and their new 2.0 equivalents (from Krzysztof Cwalina):

Non-Generic Similar Generic Type
ArrayList List<T>
Hashtable Dictionary<TKey,TValue>
SortedList SortedList<TKey,TValue>
Queue Queue<T>
Stack Stack<T>
IEnumerable IEnumerable<T>
ICollection N/A (use IEnumerable<T> or anything that extends it)
N/A ICollection<T>
IList IList<T>
CollectionBase Collection<T>
ReadOnlyCollectionBase ReadOnlyCollectionBase<T>
DictionaryBase N/A (just implement IDictionary<TKey,TValue>)
N/A SortedDictionary<TKey,TValue>
N/A KeyedCollection<TKey,TItem>
N/A LinkedList<T>


In the next part, I'll try and cut through the jargon attached to generics and also discuss some practical uses for generics in everyday coding tasks. In the meantime, check out this excellent Overview of Generics in the .NET Framework.


Tags: ,


What are C# Generics - Part I

by agrace 9. April 2008 21:10

Generic Breakfast They say the best developers are lazy. I used to believe this and would cite code reuse as justification for my inertia! For a long time now, I have been intending to use generics and collections more in my code. I guess I meant well, but in the real world we tend to go for what we know works and a syntax that we feel comfortable with. There are so many new additions to the C# langauge now that it is tempting to want to jump in and play. However, I feel that a grasp of generics is an important skill to acquire first. So, I'm going to take a walk through the generics landscape and see how it all fits together...

Here's a loose definition from a Microsoft MSDN article: "Generics are the most powerful feature of C# 2.0. Generics allow you to define type-safe data structures, without committing to actual data types. This results in a significant performance boost and higher quality code, because you get to reuse data processing algorithms without duplicating type-specific code. In concept, generics are similar to C++ templates, but are drastically different in implementation and capabilities."

Generics Generics permit us to write code where the data types aren't hard-coded. If we have a lot of code that performs the same function but on different types, then we can get big savings in terms of performance and the amount of code that we actually have to create.

Let me say two things about generics right off the bat: first, the main motivation for generics is not one of performance. Performance is more of a side effect, if you will. It is more about what the name implies, that is, it gives a level of generality to our types. It helps us to factor out the behaviour of our classes from the data upon which they act. In addition to performance gains, we profit from increased code reuse and type safety. Second, although they share a similar motivation, generics and templates are fundamentally different animals: generics are created at runtime by the CLR and templates are created at compile time by the compiler.

The designers of generics define it as "a feature that permits classes, structures, interfaces, delegates, and methods to be parameterized by the types of data they store and manipulate." The goal of this series is to demystify generics and to encourage you incorporate it into your own code, even if only in a very basic way to begin.

In the next part, we'll take a look at some specifics including where we can use generics and and how to find our way through the new terminology associated with generics. We'll save 'Parametric Polymorphism' for a later installment ;-)


Tags: ,


I recently posted a solution to the eternal PayPal / ASP.NET form submission problem using Jeremy Schneider's custom GhostForm class. Since then, several people have made mention of a problem that I came across myself when coding this, namely getting your project to recognize the reference to the new custom form class.

PayPal Checkout Button


Using a Web Application Project in VS 2005, I recently came up against something similar when attempting to place the SqlHelper.cs class in the App_Code folder. At that time I offered a quick hack. Since then, I have thought better of using the App_Code folder in my Web Application Projects and just create a normal folder and put the helper class in there along with my data access class. The App-Code is more trouble than it is worth for a small project where there is practically zero compilation time to be saved anyway.

Back to the problem at hand... when attempting to compile, you may get the following error:

"The name 'mainForm' does not exist in the current context"

First, check your scopes; make sure that wherever you are using the mainForm object is in the same scope as the instantiation. Ideally, create a separate Class Library Project in your solution and add the custom form class to it. Compile your new project separately and reference that from your e-commerce project. Right-click the References folder in Solution Explorer and browse to the DLL for the custom form.

CustomForm Class Library Project


Add the following to your master page and ignore any red squigglies you get in Visual Studio:

<%@ Register TagPrefix="CF" Namespace="CustomForm" Assembly="CustomForm" %>
    <CF:GhostForm id="mainForm" runat="server">


Add markup to the ASPX for the dummy PayPal button and a functioning ASP.NET button:

<img src="https://www.sandbox.paypal.com/en_US/i/btn/btn_xpressCheckout.gif"> <asp:Button ID="checkoutBtn" runat="server" OnClick="CheckButton_Click"
    Text="Checkout" Width="100" CausesValidation="false" /> 


using CustomForm;

namespace MyProject
    public partial class purchase : System.Web.UI.Page
        protected void Page_Load(object sender, EventArgs e)
            // Workaround for PayPal form problem
            GhostForm mainForm = new GhostForm();
            mainForm.RenderFormTag = false;


Although specific to my own project requirements, here's the complete handler code for the button click: 

        protected void CheckButton_Click(object sender, EventArgs e)
            // Live PayPal URL
            // const string SERVER_URL = "https://www.paypal.com/cgi-bin/webscr";
            // Sandbox PayPal URL
            const string SERVER_URL = "https://www.sandbox.paypal.com/cgi-bin/webscr";
            // Live business parameter
            // const string BUSINESS = "grace@graceguitars.com";
            // Sandbox business parameter
            const string BUSINESS = "tester@hotmail.com";

            // Return URL for IPN processing
            const string NOTIFY_URL = "http://www.mysite.com/PayPalReturnURL.aspx";

            decimal totalAmount = 0.00M;
            int productID = 0;
            int totalUnits = 0;
            decimal totalShipping = 0.00M;
            string paypalURL = "";
            string itemName = "Grace\'s Guitars";
            string itemNumber = "";

            if (cart.Count > 0)
                BizClass biz = new BizClass();
                // TransactionID will be later used to check against IPN info
                string transID = Guid.NewGuid().ToString();
                // Create a new Order in DB
                orderID = biz.AddOrder(out orderID, transID, false, DateTime.Now);
                itemNumber = Convert.ToString(orderID);

                foreach (ShoppingCartItem item in cart)
                    totalAmount += item.Total;
                    totalUnits += item.Units;
                    productID += item.ProductID;

                    // Store order details in database
                    biz.AddOrderDetails(orderID, productID, item.Units);
                // Eventually, use a SQL Server job to remove unconfirmed orders

                // Calculate total shipping cost for total number of units
                totalShipping = CalculateShipping(totalUnits);

                // Get back the URL-encoded URL for PayPal   
                paypalURL = GetPayPalURL(SERVER_URL, BUSINESS, itemName, itemNumber,
                    totalAmount, totalShipping, NOTIFY_URL);
                Response.Redirect(paypalURL, true);


You need to sign into your PayPal Developer account before submitting your test purchases. You will be able to see a history of your test transactions in the sandbox admin section.

PayPal Sandbox


If you want some sample code for constructing the URL, I suggest you check out the following whitepaper from Rick Strahl. This should be enough to see you up and running. Many times, people get compiler errors due to badly-formed namespace declarations and class references. Always double-check your code :-)


GhostForm.zip (448.00 bytes)