It is because compiler might think an unsafe type casting is needed if you use 'out' parameter modifier for covariance.
See this scenario. Say there is a method f expecting NotOK as input:
interface NotOK<out T>
{
bool TryDequeue(out T t);
}
void f( NotOK<Animal> x)
{
bool b ;
Animal animal_in_f;
b = x.TryDequeue(animal_in_f);
}
See what happens if I have two interfaces:
NotOK<Animal> objA;
NotOK<Dog> objD;
Use objA as input to f, no problem.
f(objA);
// objA should have a method of signature bool TryDequeue(out Animal t)
// inside method f, it calls x.TryDequeue(animal_in_f);
// where animal_in_f is Animal, type match
But if covariance is allowed, passing objD would be allowed
f(objD);
// objD should have a method of signature bool TryDequeue(out Dog t)
// inside method f, it calls x.TryDequeue(animal_in_f);
// where animal_in_f is Animal
// but this time x.TryDequeue is expecting a Dog!!
// It is unsafe to cast animal_in_f to Dog
So you see why out is not allowed to use in covariance.
I think conceptually it should work, because by using out parameter modifier we just want that passed variable as output. It will work if compiler has a special rule so that when it encounters scenario as above it should consider the casting is safe and not generate error.
However I think C# designer weighted the pros and cons and finally decided to maintain a consistent type checking rule, which is downcasting is not allowed in general.
In my opinion it is better to add that special rule because now it limits the usage, say it cannot have a method that return two objects of T type which needs the use of out parameter modifier.