Covariance and Contravariance
Covariance and contravariance are rules for when a container of one type can stand in for a container of a related type, like a basket of apples counting as a basket of fruit. They decide when that swap is safe.
In this page:
Syntax
interface IProducer<out T> { T Get(); } // covariance: out
interface IConsumer<in T> { void Use(T item); } // contravariance: in
IEnumerable<object> items = new List<string>();
Covariance and Contravariance
Covariance (out T) lets a generic interface with a more derived type be used where a less derived type is expected, like treating IEnumerable<string> as IEnumerable<object>.
Contravariance (in T) works the opposite direction for input positions, like delegates. These annotations only apply to interfaces and delegates, not classes, and only make sense for reference types.
Note:
IEnumerable<T> is covariant, which is why you can pass a List<string> anywhere an IEnumerable<object> is expected.Example: Covariance and Contravariance
using System;
using System.Collections.Generic;
class Program
{
static void PrintAll(IEnumerable<object> items)
{
foreach (object item in items)
{
Console.WriteLine(item);
}
}
static void Main(string[] args)
{
List<string> names = new List<string> { "Ana", "Bo" };
PrintAll(names); // covariance: IEnumerable<string> used as IEnumerable<object>
}
}
Login to try C/C++/Java/PHP code in the editor
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the
view already swaps in the hi_ translation fields (or blanks these
out if untranslated), so this renders correctly for both languages
without a lang_code check here. #}
Common Mistakes
- Trying to use covariance with
List<T>, which is invariant; only interfaces such asIEnumerable<out T>allow it. - Confusing
in(contravariance) without(covariance). - Using
out Ton a parameter position, which is not allowed.
🔒
Chapter Quiz — Complete all 6 topics to unlock
0/6 topics done
Complete these topics first: