I\'m having a little trouble understanding how I would use covariance and contravariance in the real world.
So far, the only examples I\'ve seen have been the same o
The in and out keywords control the compiler's casting rules for interfaces and delegates with generic parameters:
interface IInvariant {
// This interface can not be implicitly cast AT ALL
// Used for non-readonly collections
IList GetList { get; }
// Used when T is used as both argument *and* return type
T Method(T argument);
}//interface
interface ICovariant {
// This interface can be implicitly cast to LESS DERIVED (upcasting)
// Used for readonly collections
IEnumerable GetList { get; }
// Used when T is used as return type
T Method();
}//interface
interface IContravariant {
// This interface can be implicitly cast to MORE DERIVED (downcasting)
// Usually means T is used as argument
void Method(T argument);
}//interface
class Casting {
IInvariant invariantAnimal;
ICovariant covariantAnimal;
IContravariant contravariantAnimal;
IInvariant invariantFish;
ICovariant covariantFish;
IContravariant contravariantFish;
public void Go() {
// NOT ALLOWED invariants do *not* allow implicit casting:
invariantAnimal = invariantFish;
invariantFish = invariantAnimal; // NOT ALLOWED
// ALLOWED covariants *allow* implicit upcasting:
covariantAnimal = covariantFish;
// NOT ALLOWED covariants do *not* allow implicit downcasting:
covariantFish = covariantAnimal;
// NOT ALLOWED contravariants do *not* allow implicit upcasting:
contravariantAnimal = contravariantFish;
// ALLOWED contravariants *allow* implicit downcasting
contravariantFish = contravariantAnimal;
}//method
}//class
// .NET Framework Examples:
public interface IList : ICollection, IEnumerable, IEnumerable { }
public interface IEnumerable : IEnumerable { }
class Delegates {
// When T is used as both "in" (argument) and "out" (return value)
delegate T Invariant(T argument);
// When T is used as "out" (return value) only
delegate T Covariant();
// When T is used as "in" (argument) only
delegate void Contravariant(T argument);
// Confusing
delegate T CovariantBoth(T argument);
// Confusing
delegate T ContravariantBoth(T argument);
// From .NET Framework:
public delegate void Action(T obj);
public delegate TResult Func(T arg);
}//class