Pod pojmom generičko programiranje podrazumeva se izrada programskog koda koji se u nepromenjenom obliku može primeniti na različite tipove podataka.

U C#-u možemo da, između ostalog, imamo generičke klase i metode, tj klase i metode koji nisu napravljeni za neki konkretan tip ali mogu da se koriste sa bilo kojim tipom podataka.

Generički tipovi se deklarišu šiljatim zagradama < > iza kojih se navodi ime tipa.

Recimo da definišemo klasu ili metodu sa <T> i unutar te klase radimo operacije sa T. Posle prosledimo ceo broj tako što pišemo <int> - tada će T koje se nalazi unutar klase ili metode da se promeni u int prilikom kompajliranja.

(Praksa je da se između zagrada za tip koristi slovo T ukoliko se radi sa jednim parametrom ili da se koristi slovo T kao predznak - poput TKey, TValue ukoliko se deklariše više parametara. )

Primer: Generička klasa

  using System;
class Genericka<T>
{
private T generickaPromenjiva;

public Genericka(T generickaVrednost)
{
this. generickaPromenjiva = generickaVrednost;
}
public void Prikaz()
{
Console.WriteLine(this.generickaPromenjiva);
}
}
class Test
{
static void Main(string[] args)
{
Genericka<int> g = new Genericka<int>(5);
Genericka<string> g1 = new Genericka<string>("tekstualna poruka");

g.Prikaz();
g1.Prikaz();
}
}

U ovom primeru je definisana generička klasa - class Genericka<T>. Unutar klase smo tretirali T kao normalne podatke i deklarisali promenljivu tipa T - private T generickaPromenjiva; .

U konstruktoru se takođe koristi promenljiva tipa T - public Genericka(T generickaVrednost). Zapamtite da će se odluka koji će tip podataka biti to T vršiti tek prilikom kreitanja objekata klase.

Genericka<int> g = new Genericka<int>(5); - ovde je tip od T postavljen da budu celi brojevi. To znači da će unutar definicije klase T biti zamenjeno sa int.

Genericka<string> g1 = new Genericka<string>("tekstualna poruka"); - u objektu g1, T je string. To znači da će T da postane string prilikom definisanja klase.


Plastično objašnjeno na ovom primeru:

Nakon izvršavanja Genericka<int> g = new Genericka<int>(5);, generička klasa će biti ovakva:

class Genericka
{
  private int generickaPromenjiva;
  public Genericka( int generickaVrednost)
  {
    this. generickaPromenjiva = generickaVrednost;
  }
  public void Prikaz()
  {
    Console.WriteLine(this.generickaPromenjiva);
  }
}

Nakon izvršavanja Genericka<string> g1 = new Genericka<string>("tekstualna poruka");, generička klasa će biti ovakva:

class Genericka
{
  private string generickaPromenjiva;

  public Genericka(string generickaVrednost)
  {
    this. generickaPromenjiva = generickaVrednost;
  }
  public void Prikaz()
  {
    Console.WriteLine(this.generickaPromenjiva);
  }
}

Ograničenja:

U prethodnom primeru smo koristili parametar tipa kao nešto što nam čuva mesto gde će kasnije da se postavi neki konkretan tip podataka. U C#-u možemo takođe i da ograničimo koji sve tip podataka može da se koristi, korišćenjem ključne reči where.

Na primer, ako deklarišemo klasu kao:

class NazivKlase<T> where T: class

u tom slučaju, T može da bude samo referentni tip (klasa, string i slično). Ako pokušamo nešto što nije referentni tip dobićemo grešku.

Tipovi ograničenja su dati u nastavku:


Ograničenje:

Opis:

class

Mora biti referentni tip

struct

Mora biti vrednosni tip

new()

Mora da ima javni (public) konstruktor bez parametara.

BaseClassName

Mora da je izvedena iz klase BaseClassName.

InterfaceName

Mora da implementira interfejs InterfaceName.

U

Mora da bude ili da je izvedena iz argumenata koji su dati za U.


Primer:

 using System;
class Genericka<T> where T: class { public T generickaPromenjiva { get; set;} } class Test { static void Main(string[] args) { Genericka<int> g = new Genericka<int>();
g.generickaPromenjiva = 15;
Console.WriteLine(g.generickaPromenjiva); } }

U ovom primeru je postavljeno ograničenje da se umesto T može postavljati samo referentni tip podataka jer je napisano where T: class. Nakon toga je pokušano da se napravi objekat sa korišćenjem celog broja umesto T. Pošto je int vrednosni tip podataka, dobijamo grešku prilikom kompajliranja

… error CS0452: The type `int' must be a reference type in order to use it as type parameter `T' in the generic type or method `Genericka<T>' …

Međutim ...

Ako pokušamo sa referentnim tipom:

 using System;

class Genericka<T> where T: class { public T generickaPromenjiva { get; set;} } class Test { static void Main(string[] args) { Genericka<string> g = new Genericka<string>();
g.generickaPromenjiva = "poruka u stringu";
Console.WriteLine(g.generickaPromenjiva); } }

U ovom primeru je pokušano sa stringom, koji JESTE referentni tip, i stoga je kod uspešno kompajliran.

Napomena: može se koristiti više ograničenja, po potrebi.


Izvedene generičke klase:


Primer:

 using System;
 class Genericka<T> 
 {
   public T generickaPromenjiva { get; set; }
 }
 class Izvedena<T>: Genericka<T>
 {

 }
 class Test
 {
   static void Main(string[] args)
   {
     Izvedena<string> s = new Izvedena<string>();
   }
 }

Generičke metode:

Slično kao sa generičkim klasama, možemo da kreiramo i generičke metode:

Primer:

 using System;

 class Test
 {
   static void PRIKAZ<T>(T poruka)
   {
     Console.WriteLine(poruka);
   }

   static void Main(string[] args)
   {
     PRIKAZ(" Auuuuu !!! ");
     PRIKAZ(10);
   }
 }

U ovom primeru imamo generički metod PRIKAZ kojem je kao parametar tipa u špicastim zagradama napisano T.

Prvo smo metodi kao parametar prosledili string, a posle toga ceo broj – i sve treba da radi ok.

Last modified: Tuesday, 21 September 2021, 9:46 AM