Bird
Raised Fist0
C Sharp (C#)programming~10 mins

Covariance with out keyword in C Sharp (C#) - Step-by-Step Execution

Choose your learning style10 modes available
Concept Flow - Covariance with out keyword
Define interface with out T
↓
Implement interface with specific types
↓
Assign derived type instance to base type variable
↓
Use interface methods returning T
↓
Observe covariance allows safe assignment
Covariance with the out keyword lets you use a more derived type where a base type is expected, safely allowing assignment and method returns.
Execution Sample
C Sharp (C#)
interface ICovariant<out T> { T GetItem(); }
class Animal { }
class Dog : Animal { }
class DogCovariant : ICovariant<Dog> { public Dog GetItem() { return new Dog(); } }
ICovariant<Dog> dogCovariant = new DogCovariant();
ICovariant<Animal> animalCovariant = dogCovariant;
Animal animal = animalCovariant.GetItem();
This code shows how an interface with out T allows assigning ICovariant<Dog> to ICovariant<Animal> and safely getting an Animal.
Execution Table
StepActionVariable/TypeValue/TypeExplanation
1Define interface ICovariant with out TICovariant<T>Covariant interfaceInterface allows covariance on T
2Create class AnimalAnimalBase classAnimal is base type
3Create class Dog : AnimalDogDerived classDog inherits Animal
4Instantiate DogCovariant as ICovariant<Dog>dogCovariantICovariant<Dog>Instance with Dog type
5Assign dogCovariant to ICovariant<Animal>animalCovariantICovariant<Animal>Covariance allows this assignment
6Call GetItem() on animalCovariantanimalAnimalReturns Dog as Animal safely
7End--Execution ends after safe assignment and method call
💡 Covariance with out keyword allows assigning ICovariant<Dog> to ICovariant<Animal> safely, enabling polymorphic behavior.
Variable Tracker
VariableStartAfter Step 4After Step 5After Step 6Final
dogCovariantnullICovariant<Dog> instanceICovariant<Dog> instanceICovariant<Dog> instanceICovariant<Dog> instance
animalCovariantnullnullICovariant<Animal> referencing dogCovariantICovariant<Animal> referencing dogCovariantICovariant<Animal> referencing dogCovariant
animalnullnullnullAnimal (Dog instance)Animal (Dog instance)
Key Moments - 3 Insights
Why can we assign ICovariant<Dog> to ICovariant<Animal>?
Because the interface uses the out keyword, it allows covariance, meaning you can use a more derived type (Dog) where a base type (Animal) is expected, as shown in step 5 of the execution_table.
Can we use the out keyword if the type parameter is used as a method input?
No, the out keyword restricts the type parameter to be used only in output positions (like return types). Using it as input would cause a compile error, ensuring type safety.
What type does GetItem() return when called on animalCovariant?
It returns an Animal type, but the actual object is a Dog instance, as shown in step 6 of the execution_table.
Visual Quiz - 3 Questions
Test your understanding
Look at the execution_table at step 5, what type is animalCovariant assigned?
AICovariant<Dog>
BICovariant<Animal>
CDog
DAnimal
💡 Hint
Check the 'Variable/Type' and 'Value/Type' columns at step 5 in execution_table.
At which step does the GetItem() method return an Animal type?
AStep 6
BStep 5
CStep 4
DStep 7
💡 Hint
Look at the 'Action' and 'Value/Type' columns in execution_table for when GetItem() is called.
If the interface did not use the out keyword, what would happen at step 5?
AAssignment would be allowed without error
BRuntime error occurs
CCompile-time error due to type incompatibility
DGetItem() would return null
💡 Hint
Covariance requires the out keyword; without it, assignment between ICovariant and ICovariant is invalid.
Concept Snapshot
Covariance with out keyword:
- Use 'out' on generic interface type parameter to enable covariance.
- Allows assignment from ICovariant<Derived> to ICovariant<Base>.
- Type parameter can only be used as method return (output).
- Enables safe polymorphic behavior in generic interfaces.
Full Transcript
Covariance with the out keyword in C# allows a generic interface to be safely assigned from a more derived type to a base type. The interface declares the type parameter with 'out', meaning it can only be used as a return type, not as input. This enables code like assigning ICovariant<Dog> to ICovariant<Animal> without errors. When calling methods like GetItem(), the returned object is safely treated as the base type, even if the actual object is derived. This concept helps write flexible and type-safe code using generics.

Practice

(1/5)
1.

What does the out keyword do when used in a generic interface in C#?

easy
A. It makes the generic type parameter covariant, allowing assignment of derived types to base types.
B. It makes the generic type parameter contravariant, allowing assignment of base types to derived types.
C. It restricts the generic type parameter to value types only.
D. It allows the generic type parameter to be used as an input parameter only.

Solution

  1. 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.
  2. Step 2: Role of out keyword

    The out keyword marks a generic type parameter as covariant, enabling this safe assignment.
  3. Final Answer:

    It makes the generic type parameter covariant, allowing assignment of derived types to base types. -> Option A
  4. Quick Check:

    Covariance = out keyword [OK]
Hint: Remember: out means output, so covariance applies [OK]
Common Mistakes:
  • Confusing covariance with contravariance
  • Thinking out restricts to value types
  • Assuming out allows input parameters
2.

Which of the following is the correct syntax to declare a covariant generic interface named IReadOnlyList with type parameter T?

?
easy
A. interface IReadOnlyList { T GetItem(int index); }
B. interface IReadOnlyList { void Add(T item); }
C. interface IReadOnlyList<T> { void Add(T item); }
D. interface IReadOnlyList { T GetItem(int index); }

Solution

  1. Step 1: Identify covariance syntax

    Covariance uses the out keyword before the generic type parameter in the interface declaration.
  2. Step 2: Check method signatures

    Covariant type parameters can only be used in output positions (like return types), so T GetItem(int index) is valid, but void Add(T item) is not.
  3. Final Answer:

    interface IReadOnlyList<out T> { T GetItem(int index); } -> Option D
  4. Quick Check:

    Covariant interface = out T with output methods [OK]
Hint: Covariant types use out and only return T, no input params [OK]
Common Mistakes:
  • Using in instead of out for covariance
  • Including input parameters of type T in covariant interfaces
  • Omitting the out keyword
3.

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?

medium
A. Compilation error due to invalid assignment from IProducer<Dog> to IProducer<Animal>.
B. The code compiles and runs, returning an Animal object from Produce().
C. Runtime error because of invalid cast between Dog and Animal.
D. The Produce() method returns null.

Solution

  1. Step 1: Understand covariance with out

    The interface IProducer<out T> is covariant, so IProducer<Dog> can be assigned to IProducer<Animal>.
  2. Step 2: Analyze the code behavior

    The assignment is valid and Produce() returns a Dog instance, which is safely assigned to an Animal variable.
  3. Final Answer:

    The code compiles and runs, returning an Animal object from Produce(). -> Option B
  4. Quick Check:

    Covariance allows assignment and safe return [OK]
Hint: Covariant interfaces allow assignment from derived to base types [OK]
Common Mistakes:
  • Expecting compilation error on assignment
  • Confusing covariance with contravariance
  • Thinking runtime cast error will occur
4.

Given the interface declaration interface IConsumer { void Consume(T item); }, what is the problem with this code?

medium
A. The interface should use in instead of out for input parameters.
B. No problem; the code compiles and works fine.
C. Compilation error because out cannot be used with input parameters like T item.
D. Runtime error due to invalid variance usage.

Solution

  1. Step 1: Understand variance rules for out

    The out keyword marks a type parameter as covariant, which means it can only be used in output positions (return types), not input parameters.
  2. Step 2: Analyze the interface method

    The method void Consume(T item) uses T as an input parameter, which is not allowed for covariant type parameters.
  3. Final Answer:

    Compilation error because out cannot be used with input parameters like T item. -> Option C
  4. Quick Check:

    out forbids input parameters [OK]
Hint: Covariant out types cannot appear as method inputs [OK]
Common Mistakes:
  • Using out with input parameters
  • Confusing out with in keyword
  • Ignoring compiler errors on variance misuse
5.

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?

hard
A. Assigning ISource<Apple> to ISource<Fruit> is valid due to covariance.
B. Assigning ITarget<Fruit> to ITarget<Apple> is valid due to covariance.
C. Assigning ISource<Fruit> to ISource<Apple> is valid due to contravariance.
D. Assigning ITarget<Apple> to ITarget<Fruit> is valid due to contravariance.

Solution

  1. Step 1: Recall variance keywords

    ISource<out T> is covariant, allowing assignment from ISource<Derived> to ISource<Base>. ITarget<in T> is contravariant, allowing assignment from ITarget<Base> to ITarget<Derived>.
  2. Step 2: Analyze each assignment

    Assigning ISource<Fruit> to ISource<Apple> is valid due to contravariance. reverses covariance (base to derived invalid). Assigning ITarget<Fruit> to ITarget<Apple> is valid due to covariance.: valid contravariant assignment but wrong reason (not covariance). Assigning ISource<Apple> to ISource<Fruit> is valid due to covariance.: valid covariant (derived Apple to base Fruit). Assigning ITarget<Apple> to ITarget<Fruit> is valid due to contravariance. reverses contravariance (derived to base invalid).
  3. Final Answer:

    Assigning ISource<Apple> to ISource<Fruit> is valid due to covariance. -> Option A
  4. Quick Check:

    Covariance allows derived to base assignment [OK]
Hint: Covariant = out = derived to base; Contravariant = in = base to derived [OK]
Common Mistakes:
  • Mixing covariance and contravariance directions
  • Assuming contravariance applies to output interfaces
  • Confusing type parameter usage in assignments
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard