Let me try to clear things up...
Generics are stored as IL including the parameters and constraints in the metadata. Generic types are types as well, which are converted to runtime types at runtime. This is the main difference from C++ where the template types don't exist, but only the derived types; in C# the generic types exist in the DLL, but the derived types do not (until they are created at run-time).
However, there are some things the compiler does do. If you have a List.Add(T) for example, the signature for that in the IL is exactly that. However, if you call it, it resolves the method using List.Add(Foo) as method. E.g. in your IL it will show something like this (when loading a field):
ldfld class [mscorlib]System.List`1<Foo> Bar::variable
Notice that 'Foo' is here and not 'T'.
Also, if you put constraints on the T in your generics definition, they are checked compile-time against the metadata.
At this point I'd like to point out something entirely different but related. C# gains performance by lazy-generating types (in general). This is also very different from C++. You can see this in action if you experiment with static constructors and when they are called.