Witam, otóz ostatnio kłóciłem się ze znajomym, ze nie ma czegoś takiego jak iwariancja w c#, ze jest tylko kowariancja i kontrawariancja. Teraz pytanie do was czy on mial racje ? Jeżeli tak to na czym polega iwariancja ?
A nie inwariancja czasem?
Tak chodziło o inwariancje .
Prosty przykład:
using System;
using System.Collections.Generic;
public class Test
{
class A {};
class B: A {};
public static void Main()
{
List<A> listA;
List<B> listB;
listA = listB;
}
}
Kompilacja wysypuje się w miejscu przypisania. List są inwariantne, a więc wartość typu List<X> możesz przypisać do zmiennej typu List<Y> wtedy i tylko wtedy, gdy X == Y.
Disclaimer:
Z C# orłem nie jestem i nie zależy mi na tym :P
Tak twój kolega miał rację jest w C# inwariancja (ang. invariance), czyli możesz użyć tylko takiego typu jaki został zdefiniowany, czyli inwariancja nie jest ani kowariancją ani kontrawariancją. Przykładem są typy wartościowe jak i w niektórych przypadkach tyczy się to również typów referencyjnych np.:
Klasa jest zawsze inwariancyjna:
// Error
public class Foo<in T>
{
}
// Error
public class Bar<out T>
{
}
inny przykład, kontrawariancja która działa:
public class Test
{
public static void Hmm(Foo foo)
{
}
public static void Main()
{
var bar = new Bar();
// Contravariance Example
Hmm(bar);
}
public class Bar : Foo
{
}
public class Foo
{
}
}
ale jeśli parametr funkcji Hmm
zostanie oznaczymy jako ref/out powyższy kod się nie skompiluje bo w tym przypadku możesz przekazać tylko obiekt takiego typu jaki został określony w metodzie:
public class Test
{
public static void Hmm(ref Foo foo)
{
}
public static void Main()
{
// var bar = new Bar();
// Hmm(ref bar); // Error
var foo = new Foo();
Hmm(ref foo); // Ok
}
public class Bar : Foo
{
}
public class Foo
{
}
}