Kowariancja
Typ generyczny z parametrem a może być rzutowany do innego typu z parametrem b jeżeli parametr b jest typem bazowym dla typu a. Słowo kluczowe C# dla kowariancji to out.
internal interface ICovariantable<out T> where T: new () { T GetValue(); } public class MyCovariant<T> : ICovariantable<T> where T: new() { public T GetValue() { return new T(); } } public class SampleClass: object { public SampleClass() { } }
Kontrawariancja
Typ generyczny z parametrem a może być rzutowany do innego typu z parametrem b jeżeli parametr a jest typem bazowym dla typu b. Słowo kluczowe C# dla kowariancji to in.
internal interface IContravariantable<in T> { void SetValue(T param); } public class MyContravariant<T> : IContravariantable<T> { public void SetValue(T param) { Console.WriteLine("value was set"); } }
static void Main(string[] args) { //Covariance var instance1 = new MyCovariant<object>(); var instance2 = new MyCovariant<SampleClass>(); ICovariantable<object>[] instances = {instance1, instance2}; //Contravariance var instance3 = new MyContravariant<object>(); var instance4 = new MyContravariant<SampleClass>(); IContravariantable<SampleClass>[] instances2 = { instance3, instance4 }; Console.ReadKey(); }
Jeżeli nie wyspecyfikujemy parametru out dla pierwszego interfejsu, to kompilator zaprotestuje przeciwko umieszczeniu w tablicy drugiego elementu (instance2), natomiast jeżeli nie podamy in, to niedozwolone będzie umieszczenie w drugiej tablicy obiektu instance3.
Często wykorzystywane delegaty Func i Action wykorzystują kowariancję i kontrawariację: parametry wejściowe są typu in, natomiast wartości zwracane (w przypadku Func) są oznaczone jako out.
Brak komentarzy:
Prześlij komentarz