O alta colectie generica utila in .Net este Dictionary. Ea functioneaza pe principiul perechilor cheie/valoare.
Dictionarele stabilesc o relatie (“map“) intre o cheie si o valoare. De exemplu, avem numarul de identificare al unui angajat, caruia ii putem atribui un obiect care reprezinta angajatul.
Clasa generica Dictionary face parte din spatiul de nume System.Collection.Generics. Pentru folosirea ei, vom folosi:
using System.Collections.Generic;
Folosind in continuare clasa Cont, folosita in articolele despre ArrayList si List<T>, construim un dictionar care va stoca perechi cheie/valoare de tipul string/Cont:
//instanta a clasei Cont Cont contStudent = new Cont(); //dictionar de tip string/Cont Dictionary<string,Cont> dictionar = new Dictionary<string, Cont>(); //adaugam un element in dictionar dictionar.Add("Student",contStudent);
Va aparea eroare la compilare, daca vom incerca sa adaugam o valoare de alt tip decat Cont.
//eroare MyClass cls = new MyClass(); dictionar.Add("String",cls);
“cannot convert from ‘Dictionary.MyClass’ to ‘Dictionary.Cont’“.
La accesarea unui element, nu apar probleme de conversie:
dictionar["Student"].Depune(50);
Metodele ContainsKey, ContainsValue
Adaugam mai multe elemente in dictionar:
Cont contElev = new Cont(); Cont contProfesor = new Cont(); dictionar.Add("Elev", contElev); dictionar.Add("Profesor", contProfesor);
Incercam sa accesem cu ajutorul unei chei un element. Daca nici un element nu are o valoare pentru cheia respectiva, va aparea exceptia KeyNotFoundException : “The given key was not present in the dictionary”.
//exceptie dictionar["a"].Depune(50);
In cazul folosirii clasei Dictionary, se recomanda mai intai testarea cheilor pentru a vedea daca exista si de a evita primirea exceptiei, folosind metoda ContainsKey.
if (dictionar.ContainsKey("aa")) { Console.WriteLine("exista"); } else { Console.WriteLine("nu exista"); }
Clasa Dictionary contine o metoda, ContainsValue, care cauta in toata colectia dupa valoare data ca parametru:
//cautare dupa valoare if (dictionar.ContainsValue(contElev)) { Console.WriteLine("Exista..."); }
Metoda TryGetValue
TryGetValue va returna valoarea asociata unei chei. Folosirea acestei metode este eficienta atunci cand se doreste obtinerea valorilor dintr-un dictionar unde programul acceseaza frecvent chei care nu sunt in dictionar.
Metoda are doi parametri: cheie – a carei valori incercam sa o obtinem si valoare – contine valoarea asociata cheii respective, in cazul in care este gasita. Daca nu este gasita, va returna valoare implicita pentru tipul valoare.
Exemplu:
Ca sa testam daca metoda va returna corect valoarea cheii cautate, apelam metoda Depune, pentru a modifica valoarea soldului.
contElev.Depune(40); //creem o instanta de tip Cont //pentru a putea fi returnata valoare Cont cont = new Cont(); if (dictionar.TryGetValue("Elev", out cont)) { Console.WriteLine("sold {0}", cont.Sold()); } else { Console.WriteLine("Nu exista..."); }
Construim un dictionar un pic mai simplu, pentru a arata cum putem folosi KeyValuePair intr-un ciclu foreach.
Dictionary<string, int> catalog = new Dictionary<string, int>(); catalog.Add("Produs1", 200); catalog.Add("Produs2", 230); catalog.Add("Produs3", 150); foreach (KeyValuePair<string, int> pereche in catalog) { Console.WriteLine("{0},{1}", pereche.Key, pereche.Value); }
Un lucru util in folosirea clasei Dictionary, este folosirea constructorului, atunci cand se doreste construirea unei copii a unui dictionar existent. In urmatorul exemplu vom realiza o copie a dictionarului catalog.
//construim o copie //a unui dictionar existent Dictionary<string, int> copie = new Dictionary<string, int>(catalog); //afisam elementele din dictionar foreach (KeyValuePair<string, int> pereche in copie) { Console.WriteLine("{0},{1}", pereche.Key, pereche.Value); }
Pentru stergerea tuturor perechilor cheie/valoare din dictionar, se foloseste metoda Clear.
dictionar.Clear();
Daca se doreste eliminarea doar a unui element, folosim metoda Remove, care va avea ca parametru o cheie.
//eliminarea unui element dictionar.Remove("Elev");
Pentru a afla numarul de elemente, se utilizeaza proprietatea Count.
Console.WriteLine("Nr. elem. :{0}", dictionar.Count);
O lista cu membrii clasei Dictionary,se gaseste pe msdn.
Exista colectia non-generica, HashTable, care functioneaza la fel ca Dictionary, cu exceptia faptului ca opereaza pe tipuri object.
In urma articolelor despre List si Dictionary, probabil va aparea intrebarea : Care trebuie utilizata si cand? Recomandarea e ca Dictionary sa fie folosit atunci cand e nevoie de cautari (“lookups”). In cazul unei cautari in clasa List, aceasta poate cauza probleme in cazul unui numar foarte mare de elemente.
O colectie inrudita cu Dictionary este SortedDictionary, unde perechile sunt sortate dupa cheie.
Alte clase care se bazeaza pe dictionare, in .Net Framework, sunt:
HashTable (colectie de perechi cheie/valoare, organizata pe baza unui cod “hash” al cheii)
SortedList (perechi cheie/valoare care sunt sortate in functie de chei si care sunt accesate de cheie si index),
StringDictionary ( un “hashtable” cu perechi cheie/valoare doar de tip string),
ListDictionary (dictionar optimizat pentru colectii mici de obiecte, cu mai putin de 10 elemente), HybridDictionary (dictionar care se bazeaza pe ListDictionary cand numarul elementelor este mic, iar cand numarul elementelor va creste, va folosi HashTable),
NameValueCollection (dictionar de perechi nume/valoare, elementele pot fi accesate prin nume sau index).
Tipul Dictionary este util in situatiile cand e nevoie de stocarea obiectelor pe baza unui identificator unic.
Colectiile generice dau foarte mult flexibilitate si sunt recomandate inainte celor non-generice.