IEnumerable<T>
is a covariant interface. That means there's an implicit identity conversion from IEnumerable<T1>
to IEnumerable<T2>
so long as there is an implicit reference conversion or identity conversion from T1
to T2
. See the documentation on conversions for more details on this terminology.
That's most often the case if T2
is a base class (direct or indirect) of T1
, or is an interface that T1
implements. It's also the case if T1
and T2
are the same type, or if T2
is dynamic
.
In your case, you're using an IList<Dog>
, and IList<T>
implements IEnumerable<T>
. That means any IList<Dog>
is also an IEnumerable<Dog>
, so there's a implicit reference conversion to IEnumerable<Animal>
.
A few important things to note:
Only interfaces and delegate types can be covariant or contravariant. For example, List<T>
isn't covariant and couldn't be. So for example, you couldn't write:
// Invalid
List<Animal> animals = new List<Dog>();
Not all interfaces are covariant or convariant. For example, IList<T>
isn't covariant, so this isn't valid either:
// Invalid
IList<Animal> animals = new List<Dog>();
Variance doesn't work with value types, so this isn't valid:
// Invalid
IEnumerable<object> objects = new List<int>();
Generic variance is only permitted where it's safe:
- Covariance relies on the type parameter only be present in an "out" position in any signature, i.e. values can come out of the implementation, but are never accepted.
- Contravariance relies on the type parameter only being present in an "input" position in any signature, i.e. values can be passed into the implementation, but are never returned
It gets a bit confusing when the signatures accept a parameter which is itself contravariant - even though a parameter is normally an "input" position, it's sort of reversed by contravariance. For example:
public interface Covariant<out T>
{
// This is valid, because T is in an output position here as
// Action<T> is contravariant in T
void Method(Action<T> input);
}
Definitely read the linked documentation for more information though!