Instantly share code, notes, and snippets.

Embed
What would you like to do?
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