Don't know if they are most important, but I've learned the following:
Generics will only be instantiable via reflection if you don't know the frikkin type. In some cases you may need non-generic interfaces to use your generic classes in situations where the type is unknown.
I almost wrecked my head until I grocked that
public class Foo<T> where T : Foo<T> {
public T CloneMe() ...
}
is perfectly valid code and allows your base class to expose methods and properties related to the specialized class...that ended up in a definition of a state machine along its states:
public abstract class Machine<S,M> where S : State<S,M> where M : Machine<S,M> {
protected S state;
}
public abstract class State<S,M> where S : State<S,M> where M : Machine<S,M> {
protected M machine;
}
Generics can get a bit unwieldy. The other day I had this:
List<Tuple<Expression<Func<DataTable,object>>,Expression<Func<DataTable,object>>>>
phew...