Information Technology Reference
In-Depth Information
generic interfaces such that they can be treated covariantly, or contravari-
antly. Let's discuss generic covariance first, and then we'll move on to
contravariance.
This method can be called with a List<Planet>:
public static void CoVariantGeneric(
IEnumerable < CelestialBody > baseItems)
{
foreach ( var thing in baseItems)
Console .WriteLine( "{0} has a mass of {1} Kg" ,
thing.Name, thing.Mass);
}
That's because IEnumerable<T> has been augmented to limit T to only
output positions in its interface:
public interface IEnumerable < out T> : IEnumerable
{
IEnumerator <T> GetEnumerator();
}
public interface IEnumerator < out T> :
IDisposable , IEnumerator
{
T Current { get ; }
// MoveNext(), Reset() inherited from IEnumerator
}
I included both the IEnumerable<T> and IEnumerator<T> definition
here, because the IEnumerator<T> has the important restrictions. Notice
that IEnumerator<T> now decorates the type parameter T with the out
modifier. That forces the compiler to limit T to output positions. Output
positions are limited to function return values, property get accessors, and
certain delegate positions.
Therefore, using IEnumerable<out T>, the compiler knows that you will
look at every T in the sequence, but never modify the contents of the source
sequence. Treating every Planet as a CelestialBody in this case works.
IEnumerable<T> can be covariant only because IEnumerator<T> is also
covariant. If IEnumerable<T> returned an interface that was not declared
as covariant, the compiler would generate an error. Covariant types must
Search WWH ::




Custom Search