Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 16 additions & 21 deletions docs/standard/generics/covariance-and-contravariance.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
---
title: "Covariance and Contravariance in Generics"
description: Learn about covariance, which allows you to use a more derived type, and contravariance, which allows you to use a less derived type, in .NET generics.
ms.date: "03/30/2017"
ms.date: "03/09/2026"
ai-usage: ai-assisted
dev_langs:
- "csharp"
- "vb"
Expand All @@ -14,27 +15,21 @@ ms.assetid: 2678dc63-c7f9-4590-9ddc-0a4df684d42e
---
# Covariance and contravariance in generics

*Covariance* and *contravariance* are terms that refer to the ability to use a more derived type (more specific) or a less derived type (less specific) than originally specified. Generic type parameters support covariance and contravariance to provide greater flexibility in assigning and using generic types.
*Covariance* and *contravariance* describe how reference conversions work between constructed generic types when their type arguments are related by inheritance, for example, between `IEnumerable<Derived>` and `IEnumerable<Base>`. Variance is a property of a generic interface or delegate type's type parameter, and it controls which implicit conversions exist between constructed types that use different type arguments. By default, generic type parameters are *invariant*—even if one type argument derives from another, the corresponding constructed generic types, such as `List<Derived>` and `List<Base>`, are unrelated unless the type parameter is explicitly declared as *covariant* or *contravariant*.

When you're referring to a type system, covariance, contravariance, and invariance have the following definitions. The examples assume a base class named `Base` and a derived class named `Derived`.

- `Covariance`

Enables you to use a more derived type than originally specified.

You can assign an instance of `IEnumerable<Derived>` to a variable of type `IEnumerable<Base>`.

- `Contravariance`

Enables you to use a more generic (less derived) type than originally specified.

You can assign an instance of `Action<Base>` to a variable of type `Action<Derived>`.

- `Invariance`

Means that you can use only the type originally specified. An invariant generic type parameter is neither covariant nor contravariant.

You cannot assign an instance of `List<Base>` to a variable of type `List<Derived>` or vice versa.
The following definitions and examples assume a base class named `Base` and a derived class named `Derived`.

- *Invariant* type arguments require you to use exactly the type specified. You can't substitute a derived or base type.

For example, you can't assign an instance of `List<Base>` to a variable of type `List<Derived>`, or vice versa.

- *Covariant* type parameters let you substitute a more derived type for the original type argument.

For example, you can assign an instance of `IEnumerable<Derived>` to a variable of type `IEnumerable<Base>`.

- *Contravariant* type parameters let you substitute a base type for a derived type argument instead of the original.

For example, you can assign an instance of `Action<Base>` to a variable of type `Action<Derived>`.

Covariant type parameters enable you to make assignments that look much like ordinary [Polymorphism](../../csharp/fundamentals/object-oriented/polymorphism.md), as shown in the following code.

Expand Down