Covariance and Contraviarance
namespace VarianceExample | |
{ | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
ISkinned<Fruit> skinnedFruit = null; | |
ISkinned<Banana> banana = null; | |
ICovariantSkinned<Fruit> covariantSkinnedFruit = null; | |
ICovariantSkinned<Banana> covariantBanana = null; | |
IContravariantSkinned<Fruit> contravariantSkinnedFruit = null; | |
IContravariantSkinned<Banana> contravariantBanana = null; | |
Peel(skinnedFruit); | |
// Peel(bananaFruit); // cannot convert from 'ISkinned<Banana>' to 'ISkinned<Fruit>' | |
// PeelBanana(skinnedFruit); // cannot convert from 'ISkinned<Fruit>' to 'ISkinned<Banana>' | |
PeelBanana(banana); | |
PeelCovariant(covariantSkinnedFruit); | |
PeelCovariant(covariantBanana); // ok, since 'in T' generic type specified | |
PeelBananaContravariant(contravariantSkinnedFruit); // ok, since 'out T' generic type specified | |
PeelBananaContravariant(contravariantBanana); | |
} | |
static void Peel(ISkinned<Fruit> param) { } | |
static void PeelBanana(ISkinned<Banana> param) { } | |
static void PeelCovariant(ICovariantSkinned<Fruit> param) { } | |
static void PeelBananaContravariant(IContravariantSkinned<Banana> param) { } | |
} | |
class Fruit { } | |
class Banana : Fruit { } | |
interface ISkinned<T> { } | |
interface ICovariantSkinned<out T> | |
{ | |
T Get(); | |
// void Set(T outParam); // Invalid variance: The type parameter 'T' must be contravariantly valid on 'ICovariantSkinned<T>.Set(T)'. 'T' is covariant. | |
} | |
interface IContravariantSkinned<in T> | |
{ | |
// T GetT(); // Invalid variance: The type parameter 'T' must be covariantly valid on 'IContravariantSkinned<T>.GetT()'. 'T' is contravariant. | |
void Set(T inParam); | |
} | |
} | |
// Based on https://stackoverflow.com/a/20660947/5540176 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment