Covariance lets you use a more specific type than originally expected when working with interfaces or delegates. The out keyword helps make this safe and easy.
Covariance with out keyword in C Sharp (C#)
interface IEnumerable<out T> { T GetItem(); }
The out keyword marks the generic type parameter as covariant.
Covariance works only for output (return) types, not input (method parameters).
T is covariant.IEnumerable<string> strings = new List<string>(); IEnumerable<object> objects = strings; // Allowed because of covariance
out keyword allows IFactory<Derived> to be used where IFactory<Base> is expected.interface IFactory<out T> { T Create(); }
This program shows how a list of Dog can be assigned to a variable of IEnumerable<Animal> because of covariance with the out keyword.
using System; using System.Collections.Generic; class Animal { public virtual string Speak() => "Animal sound"; } class Dog : Animal { public override string Speak() => "Woof"; } class Program { static void Main() { IEnumerable<Dog> dogs = new List<Dog> { new Dog() }; IEnumerable<Animal> animals = dogs; // Covariance with out keyword foreach (var animal in animals) { Console.WriteLine(animal.Speak()); } } }
Covariance only works with interfaces and delegates that have out on their generic type parameters.
You cannot use covariant types as method input parameters.
This helps make your code more flexible and type-safe when working with inheritance.
Use out to make generic type parameters covariant.
Covariance allows assigning more derived types to less derived types safely.
It works only for output positions like return types, not input parameters.
Practice
What does the out keyword do when used in a generic interface in C#?
Solution
Step 1: Understand covariance in C# generics
Covariance allows a more derived type to be assigned to a less derived type safely, typically for output positions.Step 2: Role of
Theoutkeywordoutkeyword marks a generic type parameter as covariant, enabling this safe assignment.Final Answer:
It makes the generic type parameter covariant, allowing assignment of derived types to base types. -> Option AQuick Check:
Covariance =outkeyword [OK]
out means output, so covariance applies [OK]- Confusing covariance with contravariance
- Thinking
outrestricts to value types - Assuming
outallows input parameters
Which of the following is the correct syntax to declare a covariant generic interface named IReadOnlyList with type parameter T?
?
Solution
Step 1: Identify covariance syntax
Covariance uses theoutkeyword before the generic type parameter in the interface declaration.Step 2: Check method signatures
Covariant type parameters can only be used in output positions (like return types), soT GetItem(int index)is valid, butvoid Add(T item)is not.Final Answer:
interface IReadOnlyList<out T> { T GetItem(int index); } -> Option DQuick Check:
Covariant interface =out Twith output methods [OK]
out and only return T, no input params [OK]- Using
ininstead ofoutfor covariance - Including input parameters of type T in covariant interfaces
- Omitting the
outkeyword
Consider the following code snippet:
interface IProducer { T Produce(); }
class Animal { }
class Dog : Animal { }
IProducer<Dog> dogProducer = new DogProducer();
IProducer<Animal> animalProducer = dogProducer;
Animal animal = animalProducer.Produce();What is the output or result of this code?
Solution
Step 1: Understand covariance with
The interfaceoutIProducer<out T>is covariant, soIProducer<Dog>can be assigned toIProducer<Animal>.Step 2: Analyze the code behavior
The assignment is valid andProduce()returns aDoginstance, which is safely assigned to anAnimalvariable.Final Answer:
The code compiles and runs, returning an Animal object from Produce(). -> Option BQuick Check:
Covariance allows assignment and safe return [OK]
- Expecting compilation error on assignment
- Confusing covariance with contravariance
- Thinking runtime cast error will occur
Given the interface declaration interface IConsumer { void Consume(T item); }, what is the problem with this code?
Solution
Step 1: Understand variance rules for
Theoutoutkeyword marks a type parameter as covariant, which means it can only be used in output positions (return types), not input parameters.Step 2: Analyze the interface method
The methodvoid Consume(T item)usesTas an input parameter, which is not allowed for covariant type parameters.Final Answer:
Compilation error becauseoutcannot be used with input parameters likeT item. -> Option CQuick Check:
outforbids input parameters [OK]
out types cannot appear as method inputs [OK]- Using
outwith input parameters - Confusing
outwithinkeyword - Ignoring compiler errors on variance misuse
You have the following interfaces and classes:
interface ISource { T Get(); }
interface ITarget { void Set(T item); }
class Fruit { }
class Apple : Fruit { }
ISource<Apple> appleSource = new AppleSource();
ITarget<Fruit> fruitTarget = new FruitTarget();Which of the following assignments is valid and why?
Solution
Step 1: Recall variance keywords
ISource<out T>is covariant, allowing assignment fromISource<Derived>toISource<Base>.ITarget<in T>is contravariant, allowing assignment fromITarget<Base>toITarget<Derived>.Step 2: Analyze each assignment
AssigningISource<Fruit>toISource<Apple>is valid due to contravariance. reverses covariance (base to derived invalid). AssigningITarget<Fruit>toITarget<Apple>is valid due to covariance.: valid contravariant assignment but wrong reason (not covariance). AssigningISource<Apple>toISource<Fruit>is valid due to covariance.: valid covariant (derived Apple to base Fruit). AssigningITarget<Apple>toITarget<Fruit>is valid due to contravariance. reverses contravariance (derived to base invalid).Final Answer:
Assigning ISource<Apple> to ISource<Fruit> is valid due to covariance. -> Option AQuick Check:
Covariance allows derived to base assignment [OK]
- Mixing covariance and contravariance directions
- Assuming contravariance applies to output interfaces
- Confusing type parameter usage in assignments
Ready to prove it?
Pass the test and this pattern moves unknown
