Home >Backend Development >C++ >How Do Covariance and Contravariance Enhance Type Safety and Flexibility in C# Interfaces?
Covariant and contravariant interfaces in C#
Covariant and contravariant interfaces in C# provide greater flexibility when dealing with types and their inheritance hierarchies.
Covariant interface (out T)
Covariant interfaces specify that generic type parameters can be treated as higher-level types in the inheritance hierarchy. For an interface declared as interface IBibble<out T>
, you can think of the interface reference as representing a type derived from T.
Inverter interface (in T)
Contravariant interfaces allow generic type parameters to be treated as lower-level types in the inheritance hierarchy. When an interface is defined as interface IBibble<in T>
, the interface reference can be considered a type representing the base type of T.
Practical applications of covariance
Covariance allows you to treat a collection of a derived type as if it were a collection of a base type. For example, consider a list of animals, each with a name. You can safely retrieve the names of all animals because all animals have names.
Practical application of inverter
Contravariance allows adding derived types to a collection of base types. For example, if you have access to an Animals collection and need to add a fish to it, you can do so because all fish are animals. However, trying to retrieve fish from the collection is not allowed because there is no guarantee that the collection only contains fish.
Input and output location
In C# 4.0, the in
and out
keywords explicitly mark interfaces as covariant or contravariant. in
specifies the input location (method parameters, write-only properties), while out
indicates the output location (method return value, read-only properties, out
method parameters).
Example
The following example demonstrates covariance and contravariance:
<code class="language-csharp">interface IBibbleOut<out T> { } interface IBibbleIn<in T> { } class Program { static void Main(string[] args) { var b = GetOutDescendant(); // b只能保存Descendant对象 var d = GetInBase(); // d可以接收Base和Descendant对象 } static IBibbleOut<Descendant> GetOutDescendant() { return null; } static IBibbleIn<Base> GetInBase() { return null; } } class Base { } class Descendant : Base { }</code>
Without covariance and contravariance, the compiler will not be able to guarantee type safety in the example code, which may lead to errors.
The above is the detailed content of How Do Covariance and Contravariance Enhance Type Safety and Flexibility in C# Interfaces?. For more information, please follow other related articles on the PHP Chinese website!