A .NET type is built from other types. At the core, you have classes, structures, interfaces, enumerations, and delegates. Generics give you a way of composing those core types into more complex types. This composition occurs at compile time, not at run time, so all of the type checking is performed ahead of time. And since Visual Studio recognizes generics, intellisense works too. This is an incredibly powerful form of code reuse.
We've used generic collections. Instead of just a list of objects, we can declare a list of Person. This is good, because the compiler helps us ensure that only Person objects are stored in the list. It also eliminates the unnecessary cast as we extract a Person from the list. And finally, this lets us type a dot after a list method and see the properties of a Person.
But the power of generics goes deeper than that. They let you declaratively compose types in order to create behaviors in relatively few lines of code. Instead of creating a custom class off in another file to perform a specific function, you can put together pieces right where you need them. This composition is declarative, so your intent is captured as concisely as possible. To get started, you need to master the syntax and learn a few basic patterns.