From 38b1e32fb8bfdf9590376586512814028d1a38e0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 9 Mar 2026 13:19:25 +0000 Subject: [PATCH 1/5] Initial plan From 7494d1d3a3e6dc0817ec1c385bbcc9d5b5584e2b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 9 Mar 2026 13:22:09 +0000 Subject: [PATCH 2/5] Improve covariance/contravariance definitions to be more user-focused Co-authored-by: BillWagner <493969+BillWagner@users.noreply.github.com> --- .../generics/covariance-and-contravariance.md | 37 ++++++++----------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/docs/standard/generics/covariance-and-contravariance.md b/docs/standard/generics/covariance-and-contravariance.md index db5aa04d30fa9..d78779ff9ad4a 100644 --- a/docs/standard/generics/covariance-and-contravariance.md +++ b/docs/standard/generics/covariance-and-contravariance.md @@ -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" @@ -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 generic type parameters relate to the type hierarchy. When you encounter a generic type parameter, it's either covariant, contravariant, or invariant—and this determines what types you can use in place of the specified type. Generic type parameters support covariance and contravariance to provide greater flexibility in assigning and using generic types. -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` to a variable of type `IEnumerable`. - -- `Contravariance` - - Enables you to use a more generic (less derived) type than originally specified. - - You can assign an instance of `Action` to a variable of type `Action`. - -- `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` to a variable of type `List` or vice versa. +The following definitions and examples assume a base class named `Base` and a derived class named `Derived`. + +- *Covariant* type parameters let you use a more derived type than originally specified. + + For example, you can assign an instance of `IEnumerable` to a variable of type `IEnumerable`. + +- *Contravariant* type parameters let you use a more generic (less derived) type than originally specified. + + For example, you can assign an instance of `Action` to a variable of type `Action`. + +- *Invariant* type parameters require you to use exactly the type specified. You can't use a more derived or more generic type. + + For example, you can't assign an instance of `List` to a variable of type `List`, or vice versa. 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. From dab11bd071673374cd3644922801e5e55e4fad9f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 9 Mar 2026 20:39:20 +0000 Subject: [PATCH 3/5] Address review: use 'type argument' terminology and put invariant first Co-authored-by: BillWagner <493969+BillWagner@users.noreply.github.com> --- .../generics/covariance-and-contravariance.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/standard/generics/covariance-and-contravariance.md b/docs/standard/generics/covariance-and-contravariance.md index d78779ff9ad4a..244f637dfa531 100644 --- a/docs/standard/generics/covariance-and-contravariance.md +++ b/docs/standard/generics/covariance-and-contravariance.md @@ -15,21 +15,21 @@ ms.assetid: 2678dc63-c7f9-4590-9ddc-0a4df684d42e --- # Covariance and contravariance in generics -*Covariance* and *contravariance* describe how generic type parameters relate to the type hierarchy. When you encounter a generic type parameter, it's either covariant, contravariant, or invariant—and this determines what types you can use in place of the specified type. Generic type parameters support covariance and contravariance to provide greater flexibility in assigning and using generic types. +*Covariance* and *contravariance* describe how a generic type argument can be substituted for a different type in a conversion. By default, a generic type argument is *invariant*—you must use exactly the type specified. Some generic interfaces and delegates support *covariant* or *contravariant* type parameters, which allow substitution with a more derived or more generic type. The following definitions and examples assume a base class named `Base` and a derived class named `Derived`. -- *Covariant* type parameters let you use a more derived type than originally specified. +- *Invariant* type arguments require you to use exactly the type specified. You can't substitute a more derived or more generic type. - For example, you can assign an instance of `IEnumerable` to a variable of type `IEnumerable`. + For example, you can't assign an instance of `List` to a variable of type `List`, or vice versa. -- *Contravariant* type parameters let you use a more generic (less derived) type than originally specified. +- *Covariant* type arguments let you use a more derived type than originally specified. - For example, you can assign an instance of `Action` to a variable of type `Action`. + For example, you can assign an instance of `IEnumerable` to a variable of type `IEnumerable`. -- *Invariant* type parameters require you to use exactly the type specified. You can't use a more derived or more generic type. +- *Contravariant* type arguments let you use a more generic (less derived) type than originally specified. - For example, you can't assign an instance of `List` to a variable of type `List`, or vice versa. + For example, you can assign an instance of `Action` to a variable of type `Action`. 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. From 22b6b5ff1c83568d6bac907ddcec1193b0750768 Mon Sep 17 00:00:00 2001 From: Bill Wagner Date: Tue, 10 Mar 2026 14:15:16 -0400 Subject: [PATCH 4/5] Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- docs/standard/generics/covariance-and-contravariance.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/standard/generics/covariance-and-contravariance.md b/docs/standard/generics/covariance-and-contravariance.md index 244f637dfa531..c44b8bb5682e8 100644 --- a/docs/standard/generics/covariance-and-contravariance.md +++ b/docs/standard/generics/covariance-and-contravariance.md @@ -15,11 +15,11 @@ ms.assetid: 2678dc63-c7f9-4590-9ddc-0a4df684d42e --- # Covariance and contravariance in generics -*Covariance* and *contravariance* describe how a generic type argument can be substituted for a different type in a conversion. By default, a generic type argument is *invariant*—you must use exactly the type specified. Some generic interfaces and delegates support *covariant* or *contravariant* type parameters, which allow substitution with a more derived or more generic type. +*Covariance* and *contravariance* describe how reference conversions work between constructed generic types when their type arguments are related by inheritance, for example, between `IEnumerable` and `IEnumerable`. 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` and `List`, are unrelated unless the type parameter is explicitly declared as *covariant* or *contravariant*. 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 more derived or more generic type. +- *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` to a variable of type `List`, or vice versa. From a7caa3c36db188ae09b7d538d5e38c6596bfb307 Mon Sep 17 00:00:00 2001 From: Bill Wagner Date: Tue, 10 Mar 2026 14:15:28 -0400 Subject: [PATCH 5/5] Apply suggestions from code review --- docs/standard/generics/covariance-and-contravariance.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/standard/generics/covariance-and-contravariance.md b/docs/standard/generics/covariance-and-contravariance.md index c44b8bb5682e8..ab9ebbf65e76f 100644 --- a/docs/standard/generics/covariance-and-contravariance.md +++ b/docs/standard/generics/covariance-and-contravariance.md @@ -23,11 +23,11 @@ The following definitions and examples assume a base class named `Base` and a de For example, you can't assign an instance of `List` to a variable of type `List`, or vice versa. -- *Covariant* type arguments let you use a more derived type than originally specified. +- *Covariant* type parameters let you substitute a more derived type for the original type argument. For example, you can assign an instance of `IEnumerable` to a variable of type `IEnumerable`. -- *Contravariant* type arguments let you use a more generic (less derived) type than originally specified. +- *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` to a variable of type `Action`.