I noticed a posting on Generics on the main page, and I thought I would add my own 2 cents. Hopefully this will help clear up what Generics are, how they are different from derived classes, and when a designer might choose to use them over derived classes.
First, a definition: Generics are nothing more than a class template, into which the compiler will drop whatever type(s) you like (within the generic definition's constraints, of course). In other words, roughly put, instead of cutting and pasting to create several functionally identical classes whose only difference is the types they operate on, let the compiler do the "cutting and pasting" for you.
So, when would one use generics as opposed to, say, derived classes? Here's a simple example.
Let's say that you have separate FIFO queues, each of which handle different types.
You could define a class that simply stores the queue items as objects. But these are not type-safe, you would need to do casting, and there's that boxing/unboxing problem for value types. Plus the overhead incurred from the compiler having to maintain virtual method pointer tables (with the caveat that I remember this from my old C++ compiler days, it's possible the .net runtime has optimized this).
So you create derived classes from the base class that each are of the required type. So that buys you type-safety and eliminates casting, but it doesn't help you with the boxing/unboxing of value types, which would still be stored as an Object reference in the base class. Worse, if there are any other methods that need to be type-safe, which there almost certainly will be, then you have to duplicate (cut/paste/modify) each of those methods in each of your derived classes. So we're starting to get pretty far away from "code reuse."
Generics promise full code reusability. You write the code once, and literally drop in the types that the class will operate on when you instantiate the class. Type-safe, fast, flexible, extensible, and fully reusable.