I think you need to understand better the variance of arrays. Arrays like object[]
and string[]
came already in .NET 1, a long time before generics (.NET 2). Otherwise they might have been called Array<object>
and Array<string>
.
Now, we all know that any string
is an object
. If this fact implies, for some "construction" Xxx
, that any Xxx<string>
is an Xxx<object>
, then we call this covaraince. Since .NET 4, some generic interfaces and generic delegate types can be covarinat, and this is marked with an out
keyword in their definition, as in
public interface IEnumerable<out T>
{
// ...
}
If the relation is reversed upon "applying" Xxx<>
, then that's called contravariance. So "string
is object
" with contravariance becomes "Xxx<object>
is Xxx<string>
".
Now, back to arrays. The natural question here is: Are arrays covariant or contravariant or neither ("invariant")? Since you can both read from and write to each "cell" in an array, they can't be fully covariant or contravariant. But try this code:
string[] arr1 = { "these", "are", "strings", };
object[] arr2 = arr1; // works! covariance!
var runtimeType = arr2.GetType(); // System.String[]
So a T[]
is covariant in .NET. But didn't I just say I could write (like in
not out
) to an array? So what if I continue like this:
arr2[0] = new object();
I'm trying to put an object
which is not a string
into the zeroth slot. The above line has to compile (compile-time type of arr2
is object[]
). But it also has to raise an excpetion run-time. That's the problem with arrays and covariance.
So what about contravariance? Try this:
object[] arrA = { new object(), DateTime.Now, "hello", };
string[] arrB = arrA; // won't compile, no cotravariance
Making an explicit cast from object[]
to string[]
still won't work runtime.
And now, the answer to your question: You are trying to apply contravariance to arrays. AbilityResult
is Component
, but that does not imply that Component[]
is AbilityResult[]
. Whoever wrote the GetElementsInSomeWay()
method, chose to create a new Component[]
. Even if all components he put into it, are AbilityResult
, there's still no contravariance. The author of GetElementsInSomeWay()
could have chosen to make a new AbilityResult[]
instead. He could still have return type Component[]
beacuase of the covariance of .NET arrays.
Lesson to learn: The real type (run-time type as revealed by .GetType()
) of an array will not change just because you cast. .NET does allow covariance (a variable of type Component[]
might hold an object whose real type is AbilityResult[]
). And finally, .NET does not allow contravariance (a variable of type AbilityResult[]
never holds a reference to an object of real type Component[]
).
Hope this helps. Otherwise, my answer should give you some terms you can google to find explanations superior to mine.