Could you hire me? Contact me if you like what I’ve done in this article and think I can create value for your company with my skills.

February 1, 2011 / by Zsolt Soczó

C# 4 Covariance

.NET 4-es tanfolyamhoz írok egy prezentációt. A co és -contravarianciát próbálom érhetővé tenni. Kb. ez van a slideokon:

Variance annotations – covariance 1.

class Allat { }
class Kutya : Allat { }

interface IAllatGyar<T> where T : Allat
{
T Create();
}
class AllatGyar<T> : IAllatGyar<T> where T : Allat
{
public T Create()
{
return default(T);
}
}
AllatGyar<Kutya> kutyagyar = new AllatGyar<Kutya>();
IAllatGyar<Allat> allatGyar = kutyagyar; //cast, jogos?
Allat a = allatGyar.Create(); //mit ad vissza, típusbiztos?

Type ordering
Kutya <: Allat - A Kutya az Allat osztály leszámazottja k : Kutya - k a Kutya típus egy példánya Ha k : Kutya és Kutya <: Allat, akkor k : Allat (Liskov féle helyettesítési elv) Igaz-e, hogy ha Kutya <: Allat, akkor IAllatgyar< Kutya > <: IAllatgyar< Allat > ?
Egy Kutya példány implicit castolható Allattá. Az Allatgyar< Kutya > típusbiztosan castolható-e Allatgyar< Allat >-tá?
Ha csak kimeneti paraméterként vagy visszatérési értékként jön ki T, akkor igen, mert Kutya <: Allat, így minden kimeneti paraméternél a Allat referenciával biztonságosan elérhető egy leszármazott Kutya példány is. Ha igen, akkor T covariant, mert a típusparaméterek type orderingje érvényes a típust használó generikus típusra is, ugyanabban a sorrendben (Kutya <: Allat ==> IAllatgyar< Kutya > <: IAllatgyar< Allat >).
C# 4-ben az interfész metódus vagy delegate szignatúrában az out kulcsszó jelzi ezt:

interface IAllatgyar<out T>.

Amikor ez nem megy:

class Allat { }
class Kutya : Allat { }

interface IAllatGyar<T> where T : Allat
{
T Create();
void Valami(T t); //T befelé megy!
}

AllatGyar<Kutya> kutyagyar = new AllatGyar<Kutya>();
IAllatGyar<Allat> allatGyar = kutyagyar;

kutyagyar.Valami(new Kutya()); //Ez nyilván ok

allatGyar.Valami(new Lo()); //És ez???

Ha bemeneti paraméter is T, akkor az IAllatgyar< Allat > statikus típuson, amely valójában a IAllatgyar< Kutya > dinamikus típusra mutat átadható lenne más állat is, pl. Ló, amely szintén Allat leszármazott, de az nyilvánvaló runtime hibát okozna. Ezért nem lehet covariant T, ha az interfészen bemenetként is szerepel T.

Érhető ez így? Bármilyen javaslatot szívesen fogadok. A delegatekhez is írok persze anyagot, ez csak az eleje.

Could you hire me? Contact me if you like what I’ve done in this article and think I can create value for your company with my skills.

LEAVE A COMMENT

4 COMMENTS

  • hrongyorgy February 2, 2011

    “Az Allatgyar típusbiztosan castolható-e Allatgyar-tá?”
    Csunya lenne, ha a sajat osztalyara nem lenne castolhato. Viszont a ragozast elbokted.

    Egyebkent sztem az a baj, hogy idekeverted mar az elejebe a Generic-eket. Nem tudom, hogy a C# hogy all vele, de a Java-ban a Generic es a sima inheritance kicsit meg van kavarva.

  • Soczó Zsolt February 2, 2011

    Oh, a generikus kacsacsőrök lemaradtak a html miatt, így elég értelmetlen lett, bocs. Javítom.

  • Soczó Zsolt February 2, 2011

    Lehet a 2.0-s delegate varianciákat rakom előre majd, és utána a 4.0-s generikusokat…

  • hrongyorgy February 9, 2011

    Tipp: &lt; = < es &gt; = >