SUMMARY: Generic programming is a style of computer programming in which algorithms are written in terms of to-be-specified-later types that are then instantiated when needed for specific types provided as parameters.
Blah blah blah, why don't you answer the question instead of linking to some reference site.
linkpraveen: if you use a List<Invoice>, for example, it's impossible to have anything in that list which is not an invoice. If you just used an ArrayList, you would increase the probability of making a mistake and putting something of the wrong type in. Generics also let you make guarantees that somebody's passing something sensible into your function. For example, consider the function
T MaxBy<T>(List<T> values, Comparer<T> comparer);
This function can guarantee that you've supplied a comparer intend to operate on things of type T. Without generics, you'd have to write something like
object MaxBy(ArrayList list, Comparer comparer);
where a Comparer is a delegate that takes two objects as arguments. You might accidentally use a wrong delegate or change the type of the elements stored in a list you're using somewhere, and the compiler would never warn you about the error. You'd have to compensate for the lack of generics by writing more careful unit tests. Also, you'd have to double-check the documentation of more APIs.
So there is the general question asking what are the most common practical uses of generics. The most common is the simple use of generic collections, like List<T>, HashSet<T>, Dictionary<TKey, TValue>, T (which formally speaking in .NETenese isn't a generic collection), IEnumerable<T>, and so forth. The second most common use I see is the use of generic function types. I.e. Func<T>, Func<A, T>, Action<T>, Comparer<T>, and so on. You can see tons of the use of Enumerable extension methods like Enumerable::Where and so forth:
Enumerable.Range(0, n).Where(k => k % 3 != 0 && k % 5 != 0)
If there were no generic types, you'd have to write casts all over the place, or something, and it would be terribly inconvenient. The way .NET 1.1 is terribly inconvenient. You'd rather write a foreach loop and reimplement the same control structures over and over again.