недеља, 12. јун 2016.

Generičke liste u C# programskom jeziku


Prvo sam vam objasnio šta su negeneričke kolekcije; pogledajte ovde; zatim sam vam pokazao šta su generici i kako se prave; pogledajte ovde; i sad su došle na red generičke liste s kojima možete sva tri posta zaokružiti u jednu veliku celinu o svim kolekcijama uopšteno. Sa poznavanjem kolekcija vaše programiranje ali i čitanje koda drugih programera će vam biti mnogo efikasnije. Mada i dalje ostajem pri tome da po pitanju pravljenja igrica, posebno za Windows Phone aplikacije ili UWP – Universal Window Platform aplikacije izbegavate kolekcije jer su skupe. U svakom slučaju testirajte. Ali za sve ostale vrste aplikacija, kolekcije jednostavno olakšavaju programerima kodiranje i smanjuju kod. Kolekcije su uglavnom povezane za rad sa podacima koji potiču iz baza podataka, klasa ili drugih datoteka; često su isprepletene sa drugim programerskim aktivnostima poput taskova, događaja, delegata ili jednostavno služe da ispune neku kontrolu u programima sa grafičkim okruženjem; poput ListBox-a ili ComboBox-a; ali u jedno možete biti sigurni; gde su kolekcije tu su i podaci i kad manipulišete sa podacima vi to jednostavno radite preko kolekcija.



( Generičke kolekcije olakšavaju programiranje )

Uglavnom, sve što važi za generike to važi i za generičke liste. Sve generičke liste se nalaze u imenskom prostoru System.Collection.Generic; sve su parametorizovane kako bi izbegle boxing i unboxing objekata i kad radite sa generičkim listama tada radite sa tipom podataka koje ste definisali; svi elementi u kolekciji moraju da imaju isti tip podataka; i sve generičke liste su takođe safe type. Tokom vašeg programiranja češće će te koristiti generičke liste nego što će te praviti svoje generike jer već postojeće generičke liste mogu da odrade mnogobrojne poslovne zahteve. I pored toga što neke generičke liste imaju isti naziv poput negenerički kolekcija; razlikuju se po tome što zahtevaju parametre pri samoj deklaraciji iste. Znači, generičke liste koristite kada znate koji tip podataka hoćete da koristi vaša lista i kad hoćete da svaki elemenat u kolekciji bude istog tipa.

Generička kolekcija List<>


Najčešće korišćena generička kolekcija u programiranju je definitivno generička lista List<> zbog svoje jednostavnosti. Ona predstavlja listu elemenata kojoj možete pristupiti preko indeksa dok vam u isto vreme obezbeđuje mnoštvo metoda za sortiranje, traženje itd; iako se najčešće u programiranju listom jednostavno manipuliše kako vama odgovara. Jednostavno nadjačate neke metode u vašoj klasi objekta korisnim interfejsima koje će se odraziti na listu. Pogledajte sledeći primer, koji ću da malo zakomplikujem čisto da bi ste videli kako se može manipulisati listom prema vlastitim potrebama.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ListGenericCollection
{
    public class Student : IEquatable<Student> , IComparable<Student>
    {
        public int ID { get; set; }
        public string Name { get; set; }

        public override string ToString() => "ID: " + ID + "  Name: " + Name;

        public override bool Equals(object obj)
        {
            if (obj == null) return false;
            Student objAsStudent = obj as Student;
            if (objAsStudent == null) return false;
            else return Equals(objAsStudent);

        }

        public int CompareTo(Student student) => this.Name.CompareTo(student.Name);

        public override int GetHashCode() => ID;

        public bool Equals(Student other)
        {
            if (other == null) return false;
            return (this.ID.Equals(other.ID));

        }
    }
}

using System;
using static System.Console;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ListGenericCollection
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Student> students = new List<Student>();

            students.Add(new Student { ID = 10, Name = "Manuel Radovanovic" });
            students.Add(new Student { ID = 41, Name = "Ella Napolis" });
            students.Add(new Student { ID = 37, Name = "Martine Moore" });
            students.Add(new Student { ID = 55, Name = "Charles Junger" });
            students.Add(new Student { ID = 23, Name = "Antoinete Amorros" });

            WriteLine("Sorted list of students:" + Environment.NewLine);

            students.Sort();
            Print(students);

            WriteLine("Insert a new student:" + Environment.NewLine);
                      
            students.Insert(students.Count, new Student() { ID = 28, Name = "Alice Cooper" });

            students.Sort();
            Print(students);

            WriteLine("Remove the third student from the list:" + Environment.NewLine);

            students.RemoveAt(2);
            Print(students);
           
            WriteLine("Press any key to continue...");
            ReadKey();

        }

        static void Print(List<Student> students)
        {
            foreach (Student student in students)
            {
                WriteLine(student);

            }

            WriteLine();

        }
    }
}

Ukoliko obratite pažnju na samu klasu Student, primetićete da smo pored nekih nadjačanih metoda dodali i interfejs IComparable<> kako bi smo omogućili listi students da sortira našu listu prema imenu studenata. Takođe u kodu se možete videti da novog studenta stavljamo na poziciju koju broji lista ili da uklanjamo studenta sa liste na osnovu poznatog reda na listi. Kad pokrenete navedeni program, rezultat će biti sledeći:

Students passed the exam:

ID: 10  Name: Manuel Radovanovic
ID: 41  Name: Ella Napolis
ID: 37  Name: Martine Moore
ID: 55  Name: Charles Junger
ID: 23  Name: Antoinete Amorros

Sorted list of students:

ID: 23  Name: Antoinete Amorros
ID: 55  Name: Charles Junger
ID: 41  Name: Ella Napolis
ID: 10  Name: Manuel Radovanovic
ID: 37  Name: Martine Moore

Insert a new student:

ID: 28  Name: Alice Cooper
ID: 23  Name: Antoinete Amorros
ID: 55  Name: Charles Junger
ID: 41  Name: Ella Napolis
ID: 10  Name: Manuel Radovanovic
ID: 37  Name: Martine Moore

Remove the third student from the list:

ID: 28  Name: Alice Cooper
ID: 23  Name: Antoinete Amorros
ID: 41  Name: Ella Napolis
ID: 10  Name: Manuel Radovanovic
ID: 37  Name: Martine Moore

Press any key to continue...

Kako navedeni program izgleda možete pogledati i na video-u:


( C# 6.0 Tutorial - Advanced - 34. List Generic Collection )

Generička kolekcija LinkedList<>

Verovatno ste pomislili po nazivu da ova generička lista predstavlja listu Internet linkova; međutim navedena generička kolekcija je sasvim nešto drugo; samo se zove LinkedList<> i možete je koristiti za kakvu god listu želite. Uglavnom se retko koristi. Navedena lista u stvari predstavlja povezanu listu u koju se brže dodaju i uklanjaju elementi, određene operacije ne zahtevaju da se cela kolekcija kopira. Međutim, generička kolekcija LinkedList<> je u mnogim situacijama lošijih perfomansi, posebno se teže koriste sa mnogim operacijama i petlja foreach će mnogo brže pročitati generičku kolekciju List<> nego generičku kolekciju LinkedList<> ali recimo da ima neku prednost nad negeneričkom kolekcijom ArrayList. Ukoliko imate potrebu da često menjate pozicije elemenata u nizu, onda je ova generička klasa odličan izbor. U sledećem primeru pogledajte kako se ova lista koristi.

using System;
using static System.Console;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LinkedListGenericCollection
{
    class Program
    {
        static void Main(string[] args)
        {
            LinkedList<string> students = new LinkedList<string>();

            WriteLine("Add some students into the collection of students" + Environment.NewLine);

            students.AddLast("Manuel Radovanovic");
            students.AddLast("Ella Napolis");
            students.AddLast("Martine Moore");

            Print(students);

            WriteLine("Move the student Ella Napolis before Manuel Radovanovic" + Environment.NewLine);

            students.Remove("Ella Napolis");
            LinkedListNode<string> node = students.Find("Manuel Radovanovic");
            students.AddBefore(node, "Ella Napolis");

            Print(students);

            WriteLine("Add the student Antoinete Amorros on the first postion of students." + Environment.NewLine);

            students.AddFirst("Antoinete Amorros");

            Print(students);

            WriteLine("Add the student Charles Junger after Antoinete Amorros." + Environment.NewLine);

            node = students.Find("Antoinete Amorros");
            students.AddAfter(node,"Charles Junger");

            Print(students);

            WriteLine("Press any key to continue...");
            ReadKey();

        }

        static void Print (LinkedList<string> students)
        {
            foreach (string student in students)
            {
                WriteLine(student);

            }

            WriteLine();
        }
    }
}

Kad pokrenete navedeni program, rezultat će biti sledeći:

Add some students into the collection of students

Manuel Radovanovic
Ella Napolis
Martine Moore

Move the student Ella Napolis before Manuel Radovanovic

Ella Napolis
Manuel Radovanovic
Martine Moore

Add the student Antoinete Amorros on the first postion of students.

Antoinete Amorros
Ella Napolis
Manuel Radovanovic
Martine Moore

Add the student Charles Junger after Antoinete Amorros.

Antoinete Amorros
Charles Junger
Ella Napolis
Manuel Radovanovic
Martine Moore

Press any key to continue...


Kako navedeni program izgleda možete pogledati i na video-u:


( C# 6.0 Tutorial - Advanced - 35. LinkedList Generic Collection )

Generička kolekcija SortedList<TKey, TValue>

SortedList<TKey, TValue> je binarno sortirana generička lista bazirana na paru key/value i samo na takav način se može koristiti. Za razliku od generičke kolekcije List<> kojoj je dovoljan i jedan parametar za korišćenje; SortedList<TKey, TValue> zahteva dva parametra od čega je jedan parametar ključ dok je drugi vrednost. Često se koristi kada vam je potrebno samo brzo sortiranje podataka. Međutim generička kolekcija SortedList<TKey, TValue> sortira podatke isključivo prema ključu. To vas ne sprečava da zamenite uloge i da na primer ime studenta tretirate kao ključ dok ID studenta kreirate u vrednost. Imajte na umu da se ovo u praksi ne radi jer ključ treba biti jedinstven dok imena mogu biti ista. Moguće je listu sortirati i prema vrednosti uz pomoć Linq izraza, međutim tada vam nebi ni trebala SortedList<TKey, TValue> generička kolekcija jer nebi koristila svoju brzu sposobnost sortiranja. U sledećom primeru ću demonstrirati kako se koristi SortedList<TKey, TValue> i samo radi demonstracije ću koristiti imena kao ključ, inače nikada nemojte koristiti ništa za ključ ukoliko niste 100% sigurni da će vam ključ uvek biti jedinstven. Pogledajte sledeći primer:   

using System;
using static System.Console;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SortedListGenericCollection
{
    class Program
    {
        static void Main(string[] args)
        {
            SortedList<string, int> students = new SortedList<string, int>();

            students.Add("Manuel Radovanovic", 10);
            students.Add("Ella Napolis", 41);
            students.Add("Martine Moore", 37);
            students.Add("Charles Junger", 55);
            students.Add("Antoinete Amorros", 23);
                       
            WriteLine("Sort Students, set by Key like as Name and Value like as Key: " + Environment.NewLine);

            Print(students);

            WriteLine("Press any key to continue...");
            ReadKey();

        }

        static void Print(SortedList<string,int> students)
        {
            foreach (KeyValuePair<string, int> student in students)
            {
                WriteLine($"ID: {student.Value}    Student: {student.Key}");

            }

            WriteLine();
        }
    }
}

Kad pokrenete navedeni program, rezultat će biti sledeći:

Sort Students, set by Key like as Name and Value like as Key:

ID: 23 Student: Antoinete Amorros
ID: 55 Student: Charles Junger
ID: 41 Student: Ella Napolis
ID: 10 Student: Manuel Radovanovic
ID: 37 Student: Martine Moore

Press any key to continue...

Kako navedeni program izgleda možete pogledati i na video-u:


( C# 6.0 Tutorial - Advanced - 36. SortedList Generic Collection )

Generička kolekcija Dictionary<TKey, TValue>

Rečnik ili generička kolekcija Dictionary<TKey, TValue> je upravo to što i predstavlja, rečnik. Rečnik je baziran na dva parametra, ključ i vrednost. Stime da vi rečnik možete da pretražujete i prema ključu i prema vrednosti. Navedena generička klasa se često koristi posebno kada vam je potrebno da pronalazite neku određenu vrednost prema zadatom ključu. U sledećom primeru ću vam demonstrirati kako vi možete iz generičke kolekcije List<> premestiti studente u rečnik kako bi ste manipulisali sa studentima na osnovu njihovog ID umesto indeksa kojeg sadrži generička kolekcija List<>. Pogledajte sledeći primer:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DictionaryGenericCollection
{
    public class Student
    {
        public int ID { get; set; }
        public string Name { get; set; }
       
    }
}

using System;
using static System.Console;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DictionaryGenericCollection
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Student> students = new List<Student>();

            students.Add(new Student { ID = 10, Name = "Manuel Radovanovic" });
            students.Add(new Student { ID = 41, Name = "Ella Napolis" });
            students.Add(new Student { ID = 37, Name = "Martine Moore" });
            students.Add(new Student { ID = 55, Name = "Charles Junger" });
            students.Add(new Student { ID = 23, Name = "Antoinete Amorros" });

            Dictionary<int, string> greatStudents = new Dictionary<int, string>();

            foreach (Student student in students)
            {
                greatStudents.Add(student.ID, student.Name);

            }

            WriteLine("Students: " + Environment.NewLine);

            Print(greatStudents);
           
            WriteLine("Remove Charles Junger from the dictionary:" + Environment.NewLine);

            int getKey = 0;
            foreach (KeyValuePair<int,string> item in greatStudents)
            {
                if (item.Value == "Charles Junger") getKey = item.Key;
                
            }

            greatStudents.Remove(getKey);

            Print(greatStudents);

            WriteLine("Press any key to continue...");
            ReadKey();

        }

        static void Print(Dictionary<int,string> students)
        {
            foreach (KeyValuePair<int,string> student in students)
            {
                WriteLine($"ID: {student.Key}    Student: {student.Value}");

            }

            WriteLine();
        }
    }
}

Kad pokrenete navedeni program, rezultat će biti sledeći:

Students:

ID: 10 Student: Manuel Radovanovic
ID: 41 Student: Ella Napolis
ID: 37 Student: Martine Moore
ID: 55 Student: Charles Junger
ID: 23 Student: Antoinete Amorros

Remove Charles Junger from the dictionary:

ID: 10 Student: Manuel Radovanovic
ID: 41 Student: Ella Napolis
ID: 37 Student: Martine Moore
ID: 23 Student: Antoinete Amorros

Press any key to continue...


Kako navedeni program izgleda možete pogledati i na video-u:


( C# 6.0 Tutorial - Advanced - 37. Dictionary Generic Collection )

Generička kolekcija SortedDictionary<TKey, TValue>

Prva pomisao i reakcija po pitanju generičke kolekcije SortedDictionary<TKey, TValue> kod svakog programera je definitivno, pa čekaj koja je razlika između SortedList<TKey, TValue> i SortedDictionary<TKey, TValue>? U principu obadve generičke kolekcije su identične ali neka razlika u performansama postoji. Generička kolekcija SortedList<TKey, TValue> koristi manje memorije nego generička kolekcija SortedDictionary<TKey, TValue>. Takođe, ukoliko odjednom punite sve podatke u generičku kolekciju, generička kolekcija SortedList<TKey, TValue> je definitivno brža. Dobar je izbor i ako imate većinu već sortiranih elemenata i ako vam je bitan indeks. Međutim, ako testirate insertovanje i brisanje elemenata iz generičke kolekcije, onda je brža SortedDictionary<TKey, TValue> generička kolekcija, koja se takođe češće koristi ako vam nije bitan indeks ili ako imate baš dosta elemenata koje trebate da sortirate. Iako ove razlike mogu da vam izgledaju manje bitne u većini programerskog kodiranja, u retkim situacijama mogu biti izuzetno bitne. Zato treba da imate naviku da sve što programirate i testirate. Pogledajte jednostavan sledeći primer kako se koristi SortedDictionary<TKey, TValue> generička klasa.  

using System;
using static System.Console;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DictionaryGenericCollection
{
    class Program
    {
        static void Main(string[] args)
        {
            SortedDictionary<string, int> students = new SortedDictionary<string, int>();

            students.Add("Manuel Radovanovic", 10);
            students.Add("Ella Napolis", 41);
            students.Add("Martine Moore", 37);
            students.Add("Antoinete Amorros", 23);
                    
            WriteLine("Students: " + Environment.NewLine);

            Print(students);
           
            WriteLine("Add Charles Junger in the collection:" + Environment.NewLine);

            students.Add("Charles Junger", 55);

            Print(students);

            WriteLine("Remove Martine Moore from the collection:" + Environment.NewLine);

            students.Remove("Martine Moore");

            Print(students);

            WriteLine("Press any key to continue...");
            ReadKey();

        }

        static void Print(SortedDictionary<string,int> students)
        {
            foreach (KeyValuePair<string, int> student in students)
            {
                WriteLine($"ID: {student.Value}    Student: {student.Key}");

            }

            WriteLine();

        }
    }
}

Kao što možete videti u navedenom kodu i dodavanje i uklanjanje elementa iz sortirane generičke kolekcije preko ključa je jednostavno i elementi u kolekciji će vam automatski uvek biti sortirani. Kad pokrenete navedeni kod rezultat će biti sledeći:

Students:

ID: 23 Student: Antoinete Amorros
ID: 41 Student: Ella Napolis
ID: 10 Student: Manuel Radovanovic
ID: 37 Student: Martine Moore

Add Charles Junger in the collection:

ID: 23 Student: Antoinete Amorros
ID: 55 Student: Charles Junger
ID: 41 Student: Ella Napolis
ID: 10 Student: Manuel Radovanovic
ID: 37 Student: Martine Moore

Remove Martine Moore from the collection:

ID: 23 Student: Antoinete Amorros
ID: 55 Student: Charles Junger
ID: 41 Student: Ella Napolis
ID: 10 Student: Manuel Radovanovic

Press any key to continue...


Kako navedeni program izgleda možete pogledati i na video-u:
 
 
( C# 6.0 Tutorial - Advanced - 38. SortedDictionary Generic Collection )

Generička kolekcija Queue<>

Generički red ili generička kolekcija Queue<> predstavlja isto što i red ili negenerička kolekcija Queue stime da generičkoj kolekciji trebate odrediti isti tip podataka za sve elemente. Generička kolekcija Queue<> je takođe zasnovana na FIFO – First In First Out strukturi. To znači da generička kolekcija Queue<> takođe vraća prvi dodat ili najstariji elemenat iz kolekcije. Pogledajte sledeći jednostavan primer:

using System;
using static System.Console;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace QueueGenericCollection
{
    class Program
    {
        static void Main(string[] args)
        {
            WriteLine("Numbers in the collection:" + Environment.NewLine);

            Queue<string> numbers = new Queue<string>();

            numbers.Enqueue("one");
            numbers.Enqueue("two");
            numbers.Enqueue("three");
            numbers.Enqueue("four");
            numbers.Enqueue("five");

            Print(numbers);

            WriteLine("Remove two numbers from the collection:" + Environment.NewLine);

            numbers.Dequeue();
            numbers.Dequeue();

            Print(numbers);

            WriteLine("Press any key to continue...");
            ReadKey();

        }

        static void Print(Queue<string> numbers)
        {
            foreach (string number in numbers)
            {
                WriteLine(number);

            }

            WriteLine();

        }
     }
}

Kada generičkim redovima uklonite dva elementa, generički red će ukloniti prva dva elementa iz kolekcije. Kad pokrenete navedeni program rezultat će biti sledeći:

Numbers in the collection:

one
two
three
four
five
 

Remove two numbers from the collection:

three
four
five

Press any key to continue...


Kako navedeni program izgleda možete pogledati i na video-u:


( C# 6.0 Tutorial - Advanced - 39. Queue Generic Collection )

Generička kolekcija Stack<>

Generički stek ili generička kolekcija Stack<> predstavlja isto što i red ili negenerička kolekcija Stack stime da generičkoj kolekciji trebate odrediti isti tip podataka za sve elemente. Generička kolekcija Stack<> je takođe zasnovana na LIFO – Last In First Out strukturi. To znači da generička kolekcija Stack<> takođe vraća zadnji dodat ili najmlađi elemenat iz kolekcije. Pogledajte sledeći jednostavan primer:

using System;
using static System.Console;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace StackGenericCollection
{
    class Program
    {
        static void Main(string[] args)
        {
            WriteLine("Numbers in the collection:" + Environment.NewLine);

            Stack<string> numbers = new Stack<string>();

            numbers.Push("one");
            numbers.Push("two");
            numbers.Push("three");
            numbers.Push("four");
            numbers.Push("five");

            Print(numbers);

            WriteLine("Remove two numbers from the collection:" + Environment.NewLine);

            numbers.Pop();
            numbers.Pop();

            Print(numbers);

            WriteLine("Press any key to continue...");
            ReadKey();

        }

        static void Print(Stack<string> numbers)
        {
            foreach (string number in numbers)
            {
                WriteLine(number);

            }

            WriteLine();

        }
    }
}

Kada generičkim stekovima uklonite dva elementa, generički stek će ukloniti zadnja dva elementa iz kolekcije. Kad pokrenete navedeni program rezultat će biti sledeći:

Numbers in the collection:

five
four
three
two
one

Remove two numbers from the collection:

three
two
one

Press any key to continue...

Kako navedeni program izgleda možete pogledati i na video-u:


( C# 6.0 Tutorial - Advanced - 40. Stack Generic Collection )

I za kraj ovog posta samo da napomenem da postoje i druge vrste kolekcija koje se koriste kod sinhronizovanog programiranja poput generičke kolekcije SynchronizedCollection<T> i koje su korisne kada manipulišete nitima i koje se upotrebljavaju u zavisnosti na koju verziju .Net Framework-a ciljate u vašim programima. Uglavnom se smatraju thread safe, mada nebi rekao da su u potpunosti.