Visual Studio 2010 i C# 4.0 II DIO – Co i Contra Variance


Polja u .NET-u označavana su kao kovarijantna. Isto tako pojavom Generics-a u .NET 2.0 svojstvo kovarijance i kontravarijane nije bilo podržano. U tom pogledu sljedeći kod u C# 3.0 ne može se kompajlirati:

Funkcija1<Student> studemt = () => new Student(“Šemso”, 1978, DateTime.Now);
Funkcija1<Osoba> osoba = studemt;
Akcija1<Osoba> osoba1 = (s) => { Print(s); };
Akcija1<Student> student1 = osoba1;
Funkcija1<Student> studemt = () => new Student("Šemso", 1978, DateTime.Now);
Funkcija1<Osoba> osoba = studemt;

Akcija1<Osoba> osoba1 = (s) => { Print(s); };
Akcija1<Student> student1 = osoba1;

Bez obzira što je klasa Student izvedena iz klasa Osoba, ovakva konstrukcija koda nije validna. Upravo Varijanca kao novo proširenje C# 4.0 omogućuje nam konstrukciju koda kao u prethodnom primjeru, i sigurna provjeravanje izvedenih tipova. Jednostavno rečeno Varijanca je svojstvo operatora da se ponašaju kao tipovi. Iz tog razloga definisane su osobine KoVarijanca (Co-Variance) i KontraVarijanca (Contra-Varijance). Da bi prethodni primjer bilo kompajliran bez greške potrebno je Funkciju i Akciju implementirati u smuslu Kovarijantnosti odnosno KontraVarijantnosti.

Tj.

delegate T Funkcija1<out T>();
delegate void Akcija1<in T>(T a);

Deklaracija delegata Funkcija i Akcija imaju sličnu deklaraciju osim ključnih riječi in i out. Ovo znači da prvi delegat Funkcija služi samo za čitanje (read-only) i kao takav je type safe. U slučaju da hoćemo da naš delegat bude write –only odnoso KontraVarijantan tada koristimo ključnu riječ in,  kao što je prikazano kod primjera delegata Akcija.

Čitav primjer korištenja Ko i Kontra Varijance dat je i narednom tekstu. Primjer je preuzet sa msdn i modificiran.

class Osoba
{
  public Osoba()
   { }
  public Osoba(string ime, int id)
   {
     Ime = ime;
     ID = id;
    }
  public string Ime;
  public int ID;
}

class Student : Osoba
{
  public Student()
   { }
  public Student(string ime, int id, DateTime upis)
   {
     Ime = ime;
     ID = id;
     datumUpisa = upis;
   }
  public DateTime datumUpisa;
}

class Program
{
  //Da bi razumijeli nova proširenja CoVarijanca i KontraVarijanca pokušajte
  //kompajlirati program kada obrisete ključne riječi out i in sa deklaracije ova dva delegata
  delegate T Funkcija1<out T>();
  delegate void Akcija1<in T>(T a);

  static void Main(string[] args)
   {
    Funkcija1<Student> student = () => new Student("Šemso", 1978, DateTime.Now);
    Funkcija1<Osoba> osoba = student;
    Funkcija1<Osoba> osoba2 = ()=> new Osoba("Mirso", 1555);
    Akcija1<Osoba> osoba1 = (s) => { Print(s); };
    Akcija1<Student> student1 = osoba1;

   //Ispis objekta biće student jer je objekat osoba formiran iz studenta
   Print(osoba());

   //Ispis objekta biće student
   student1(new Student("Emir", 1977, DateTime.Now.AddDays(-5)));

   //Ispis objekta Osoba
   Print(osoba2());
   Console.Read();
}

static void Print(Osoba p)
{
  Student st = p as Student;
  if (st != null)
    Console.WriteLine("Student");
  else
    Console.WriteLine("Osoba;");

  Console.WriteLine("Name: {0};", p.Ime);
  Console.WriteLine("ID:{0}", p.ID);

   if (st != null)
    Console.WriteLine("Datum:{0}", st.datumUpisa);

   Console.WriteLine("_______________________________");
 }

}

Značajno je reći da Varijanca podržavana  samo nad delegatima  i interfejsima.

Advertisement

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s