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

Covariance with out keyword in C Sharp (C#)

Choose your learning style10 modes available
Introduction

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.

When you want to return a more specific type from a method than the interface says.
When you have a collection of a derived type but want to treat it as a collection of a base type.
When you want to assign an interface of a more derived type to a variable of a less derived type.
When working with read-only data sources where you only get values out.
Syntax
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).

Examples
You can assign a list of strings to a variable expecting objects because T is covariant.
C Sharp (C#)
IEnumerable<string> strings = new List<string>();
IEnumerable<object> objects = strings; // Allowed because of covariance
The out keyword allows IFactory<Derived> to be used where IFactory<Base> is expected.
C Sharp (C#)
interface IFactory<out T> {
    T Create();
}
Sample Program

This program shows how a list of Dog can be assigned to a variable of IEnumerable<Animal> because of covariance with the out keyword.

C Sharp (C#)
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());
        }
    }
}
OutputSuccess
Important Notes

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.

Summary

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

(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