Yes, you misunderstood how the general one works. This is also the biggest limitation on the use of generic types (in fact, you should avoid them as much as possible because of this). If Derived inherits from Base, then it's usually not that Generic<Derived> is Generic<Base> . The exception is covariance and contravariance. If you define your general class as follows:
public class Generic<out T> {}
then Generic<Derived> is Generic<Base>
If you define your general class as follows:
public class Generic<in T> {}
then Generic<Base> is Generic<Derived> (unexpectedly, yes?).
Why doesn't a simple actor work? Imagine our general class is as follows:
public class Generic<T> { public void Func1(T input); public T Func2(); }
Imagine we have a Generic<Derived> object, and we use it as a Generic<Base> . In this case, Func2 works fine - it returns a Derived object, which can be a caster for Base. But Func1 will not work - we have a function that accepts a base object, but the actual object has Func1, which accepts only derivative objects, and not all base derivatives objects, right?
This example explains why input and output inheritance works. If we apply the restriction on the type parameter in the generic class, we fix that the type T can only be returned from properties or functions, but it can never be accepted as a parameter. In this case, our general class is as follows:
public class Generic<out T> { public T Func2(); }
As we exaplained in earlier Func2 will work fine if we use a Generic<Derived> object as a Generic<Base> . For the same reason for the class:
public class Generic<in T> { public void Func1(T input); }
Func1 will work fine if the Generic<Base> object is used as a Generic<Derived> - in this case we will always pass Func1 Derived objects as parameters, and Dervied is always Base by definition.