---
title: "Explain the difference between covariance and contravariance."  
description: "Explain the difference between covariance and contravariance."  
author: "ICSM Computer"  
published: 2025-06-16  
updated: 2025-06-16  
canonical: https://www.mindstick.com/interview/34247/explain-the-difference-between-covariance-and-contravariance  
category: "c#"  
tags: ["c#"]  
reading_time: 4 minutes  

---

# Explain the difference between covariance and contravariance.

### Covariance vs Contravariance in C#

These concepts apply to **generic type parameters** and determine how you can use **inheritance** in **delegates**, **interfaces**, and **generics**.

## 1. Covariance (output)

> **Allows a method to return a more derived type than specified by the generic parameter.**

- Works with `out` keyword
- Applies to **return types**
- **Preserves assignment compatibility**

### Example: Covariance with `IEnumerable<out T>`

```cs
IEnumerable<string> strings = new List<string>();
IEnumerable<object> objects = strings; // ✅ allowed: string → object
```

Here:

- `string` inherits from `object`
- `IEnumerable<out T>` is **covariant**, so you can assign a more derived type (`IEnumerable<string>`) to a base type (`IEnumerable<object>`)

### Custom Example:

```cs
public interface ICovariant<out T>
{
    T Get();
}

public class CovariantExample : ICovariant<string>
{
    public string Get() => "hello";
}

ICovariant<object> obj = new CovariantExample(); // ✅ Covariance
```

## 2. Contravariance (input)

> **Allows a method to accept a more general type than specified by the generic parameter.**

- Works with `in` keyword
- Applies to **parameter types**
- **Reverses assignment compatibility**

### Example: Contravariance with `Action<in T>`

```cs
Action<object> actObj = o => Console.WriteLine(o);
Action<string> actStr = actObj; // ✅ allowed: object ← string
```

- `string` is a subtype of `object`
- `Action<in T>` is **contravariant**, so `Action<object>` can be assigned to `Action<string>`

### Custom Example:

```cs
public interface IContravariant<in T>
{
    void Set(T value);
}

public class ContravariantExample : IContravariant<object>
{
    public void Set(object value) => Console.WriteLine(value);
}

IContravariant<string> contravariant = new ContravariantExample(); // ✅ Contravariance
```

## Summary Table

| Feature | Covariance | Contravariance |
| --- | --- | --- |
| Keyword | `out` | `in` |
| Works on | Return types | Method parameters |
| Type direction | Derived → Base (`string` → `object`) | Base → Derived (`object` → `string`) |
| Example interface | `IEnumerable<out T>` | `IComparer<in T>`, `Action<in T>` |
| Real use case | Reading/producing | Consuming |

## Real-Life Analogy

- **Covariance**: “I can treat a `Cat` like an `Animal` when returning it from a method.”
- **Contravariance**: “I can give an `Animal` to a method that expects a `Cat` because the method knows how to handle any `Animal`.”

Let me know if you'd like:

- A diagram to visualize this
- Covariance/contravariance in delegates
- How this applies to real-world APIs or event handlers

## Answers

### Answer by ICSM Computer

### Covariance vs Contravariance in C#

These concepts apply to **generic type parameters** and determine how you can use **inheritance** in **delegates**, **interfaces**, and **generics**.

## 1. Covariance (output)

> **Allows a method to return a more derived type than specified by the generic parameter.**

- Works with `out` keyword
- Applies to **return types**
- **Preserves assignment compatibility**

### Example: Covariance with `IEnumerable<out T>`

```cs
IEnumerable<string> strings = new List<string>();
IEnumerable<object> objects = strings; // ✅ allowed: string → object
```

Here:

- `string` inherits from `object`
- `IEnumerable<out T>` is **covariant**, so you can assign a more derived type (`IEnumerable<string>`) to a base type (`IEnumerable<object>`)

### Custom Example:

```cs
public interface ICovariant<out T>
{
    T Get();
}

public class CovariantExample : ICovariant<string>
{
    public string Get() => "hello";
}

ICovariant<object> obj = new CovariantExample(); // ✅ Covariance
```

## 2. Contravariance (input)

> **Allows a method to accept a more general type than specified by the generic parameter.**

- Works with `in` keyword
- Applies to **parameter types**
- **Reverses assignment compatibility**

### Example: Contravariance with `Action<in T>`

```cs
Action<object> actObj = o => Console.WriteLine(o);
Action<string> actStr = actObj; // ✅ allowed: object ← string
```

- `string` is a subtype of `object`
- `Action<in T>` is **contravariant**, so `Action<object>` can be assigned to `Action<string>`

### Custom Example:

```cs
public interface IContravariant<in T>
{
    void Set(T value);
}

public class ContravariantExample : IContravariant<object>
{
    public void Set(object value) => Console.WriteLine(value);
}

IContravariant<string> contravariant = new ContravariantExample(); // ✅ Contravariance
```

## Summary Table

| Feature | Covariance | Contravariance |
| --- | --- | --- |
| Keyword | `out` | `in` |
| Works on | Return types | Method parameters |
| Type direction | Derived → Base (`string` → `object`) | Base → Derived (`object` → `string`) |
| Example interface | `IEnumerable<out T>` | `IComparer<in T>`, `Action<in T>` |
| Real use case | Reading/producing | Consuming |

## Real-Life Analogy

- **Covariance**: “I can treat a `Cat` like an `Animal` when returning it from a method.”
- **Contravariance**: “I can give an `Animal` to a method that expects a `Cat` because the method knows how to handle any `Animal`.”

Let me know if you'd like:

- A diagram to visualize this
- Covariance/contravariance in delegates
- How this applies to real-world APIs or event handlers


---

Original Source: https://www.mindstick.com/interview/34247/explain-the-difference-between-covariance-and-contravariance

Copyright © MindStick Software Pvt. Ltd. This Markdown version is provided for developers, AI systems, and offline reading.
