Există câteva subtilități în ceea ce privește tipurile generice pe care fiecare inginer de software profesionist ar trebui să le cunoască, iar una dintre ele este umflarea codului pe care o pot provoca tipurile generice. Luați următorul cod:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
using
System;
namespace
BunaLume
{
class
Pereche<T, U>
{
public T Prima { get; set; }
public U ADoua { get; set; }
}
class
Program
{
static void Main(string[] args)
{
Pereche<int, int> p1 = new Pereche<int, int>() { Prima = 3, ADoua = 9 };
Pereche<int, string> p2 = new Pereche<int, string>() { Prima = 5, ADoua = "Maria" };
Pereche<decimal, bool> p3 = new Pereche<decimal, bool>() { Prima = 7.2M, ADoua = false };
Console.ReadLine();
}
}
}
|
Cod foarte simplu: o clasă generică cu două tipuri generice, iar în interiorul ei, două proprietăți, fiecare având unul dintre acele tipuri generice. Apoi, în cadrul metodei Main(), creăm trei instanțe ale acestei clase, folosind mai multe combinații de tipuri pentru cei doi parametri de tip generic: Pereche<int, int>, Pereche<int, string> și Pereche<decimal, bool>.
Ceea ce ar trebui să știți, și ar trebui să fie deja clar din lecțiile anterioare despre generice, este că fiecare combinație a acestor parametri generici obligă compilatorul să genereze o nouă clasă distinctă. Acest lucru este chiar logic, putem fi cu toții de acord că Pereche<int, int> nu este egală, nici nu este același tip ca Pereche<int, string>, și chiar pot să demonstrez asta:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
using
System;
namespace
BunaLume
{
class
Pereche<T, U>
{
public T Prima { get; set; }
public U ADoua { get; set; }
}
class
Program
{
static void Main(string[] args)
{
Pereche<int, int> p1 = new Pereche<int, int>() { Prima = 3, ADoua = 9 };
Pereche<int, string> p2 = new Pereche<int, string>() { Prima = 5, ADoua = "Maria" };
Pereche<decimal, bool> p3 = new Pereche<decimal, bool>() { Prima = 7.2M, ADoua = false };
Console.WriteLine(p1.GetType().Equals(p2.GetType()));
Console.ReadLine();
}
}
}
|
Codul de mai sus va afișa False la consolă, deoarece tipul lui p1 nu este cu siguranță același cu tipul lui p2.
Deci, gândiți-vă: compilatorul creează literalmente o nouă clasă pentru fiecare dintre toate permutările parametrilor generici ai claselor utilizate în codurile voastre, cu toate codurile suplimentare pe care le-ar putea conține acele clase, cu sau fără legătură cu părțile generice. Acest lucru echivalează cu copierea-lipirea acelei clase în versiuni ușor diferite și ar trebui să știți deja cât de "bună" este copierea și lipirea codului. Acest lucru este valabil mai ales în cazul tipurilor de valoare, deoarece tipurile de referință beneficiază de o ușoară optimizare din partea compilatorului, dar totuși...
Ca o temă distractivă, inspectați fișierul binar generat din codul de mai sus folosind o aplicație de decompilare, cum ar fi extensia IlSpy a Visual Studio, și vedeți cum compilatorul a generat cod nou pentru fiecare variantă a combinațiilor de parametri de tip generic.