Programowanie w języku C#. Maciej Kusy, mkusy@prz.edu.pl
Wykład 6
Kolekcje i typy generyczne
dr inż. Maciej Kusy
Katedra Podstaw Elektroniki
Wydział Elektrotechniki i Informatyki
Politechnika Rzeszowska
Programowanie w języku C#
Programowanie w języku C#. Maciej Kusy, mkusy@prz.edu.pl
Plan wykładu
•
Kolekcje
- pojęcie kolekcji, przegląd wybranych kolekcji
- kolekcja typu tablica – klasa System.Array
- kolekcja typu tablica – klasa ArrayList
- kolekcja typu kolejka (Queue)
- kolekcja typu stos (Stack)
- kolekcja typu słownik, przykład, klasa Hashtable
•
Mechanizm typów (klas) generycznych
•
Składnia klas generycznych
•
Ograniczenia parametru typu
•
Zestawienie przestrzeni nazw kolekcji
•
Klasa generyczna List<T>
•
Wyrażenia lambda
•
Obiekty typu DataSet i DataTable
2
Programowanie w języku C#. Maciej Kusy, mkusy@prz.edu.pl
Pojęcie kolekcji
Kolekcja jest grupą elementów. W środowisku .NET
kolekcje traktują te elementy jako zestaw danych (kontener) i umożliwiają wykonywanie na nim różnych operacji.
Niektóre kolekcje zawierają prostą listę elementów (stos), natomiast inne składają się z par klucz-wartość (słownik).
Kolekcje w środowisku .NET reprezentowane są przy użyciu
klas, które są bezpieczne ze względu na typ, np.: ArrayList, Queue, Stack.
3
Programowanie w języku C#. Maciej Kusy, mkusy@prz.edu.pl
Przegląd wybranych kolekcji
• Tablica reprezentowana jest przez typy:
System.Array – udostępnia statyczne metody do
przeszukiwania, modyfikacji zawartości tablic; elementy
tablicy muszą być tego samego typu; tablice o stałej długości.
ArrayList – nie ma założenia co do długości listy
(długość zmieniana dynamicznie); elastyczne dodawanie i
usuwanie elementów; może przechowywać elementy różnych
typów.
• Kolejka – kolekcja typu FIFO ( First In First Out): pierwszy element dodany do kolejki jest z niej pierwszy usuwany (np.
kolejka w sklepie) – klasa Queue.
• Stos – kolekcja typu LIFO ( Last In First Out): ostatni element dodawany i pierwszy ściągany ze stosu (np. stos
książek) – klasa Stack.
• Słownik – kolekcja zawierająca pary klucz-wartość: na podstawie klucza wyszukiwane są dane – klasa Hashta 4
ble.
Programowanie w języku C#. Maciej Kusy, mkusy@prz.edu.pl
Kolekcja typu tablica (System.Array)
Klasa System.Array – najprostsza kolekcja
(reprezentująca tablicę), dla której język C# udostępnia
wbudowaną obsługę w formie metod i właściwości.
Elementy tablicy System.Array mogą być obiektami
dowolnego (ale tego samego) typu.
Do deklaracji tablic w języku C# służy zwykła składnia, jednak w programie powstaje obiekt typu System.Array:
int [] tablica = new int[10];
W kodzie IL powstaje egzemplarz typu System.Int32[],
a to jest typ pochodny po abstrakcyjnej klasie System.Array.
Wada klasy System.Array: nie zmienia automatycznie
rozmiaru tablicy podczas dodawania/usuwania obiektów.
5
Programowanie w języku C#. Maciej Kusy, mkusy@prz.edu.pl
Wybrane składowe klasy System.Array
• Clear(⋅) –metoda statyczna przypisująca zakresowi elementów tablicy 0 lub referencję null.
• IndexOf(⋅, "-") –metoda statyczna zwracająca indeks pierwszego wystąpienia argumentu ("-" ) metody w tablicy.
• Reverse(⋅) – metoda statyczna odwracająca kolejność elementów w tablicy.
• Sort(⋅) – metoda statyczna sortująca wartości w tablicy jednowymiarowej.
• Length –właściwość zwracająca długość tablicy.
• Rank –właściwość zwracająca liczbę wymiarów tablicy.
gdzie „⋅” to np.: char [] tab = {'a','m','k'};
• Nie można tworzyć obiektów typu Array: w zamian:
Array obj = Array.CreateInstance
(Type typ, int dlugosc);
6
Programowanie w języku C#. Maciej Kusy, mkusy@prz.edu.pl
Kolekcja typu tablica (ArrayList)
Klasa ArrayList udostępnia mechanizm dynamicznej
zmiany swojego rozmiaru oraz wstawiania i usuwania
elementów w określonych miejscach.
Implementuje interfejs IList, który służy do przetwarzania zawartości kolekcji za pośrednictwem indeksu numerycznego
rozpoczynającego się od 0.
Daje możliwość pracy nad obiektami typu Object, dzięki temu obiekty klasy ArrayList mogą zawierać instancje dowolnego typu (wada: konieczność każdorazowego rzutowania typów).
Zawarta w przestrzeni nazw: System.Collections.
7
Programowanie w języku C#. Maciej Kusy, mkusy@prz.edu.pl
Wybrane składowe interfejsu IList
• int IndexOf(Object o) – metoda określająca indeks
obiektu o w kolekcji (zwraca -1, jeżeli obiekt nie istnieje).
• int Add(Object o) – metoda, która dodaje obiekt o na koniec listy i zwraca jego indeks.
• void Insert(int i, Object o) – metoda wstawiająca
pod wskazany w argumencie indeks i obiekt o do kolekcji.
• void Remove(Object o) – metoda, która służy do usuwania obiektu o z kolekcji (jeżeli istnieje).
• void RemoveAt(int i) – metoda, która usuwa z kolekcji obiekt znajdujący się pod indeksem i.
• void Clear() – metoda, która służy do usunięcia wszystkich elementów z kolekcji.
• bool Contains(Object o) – metoda zwracająca wartość
true, jeżeli kolekcji znajduje się obiekt o.
• Count – właściwość zwracająca rozmiar kolekcji.
• Capacity – właściwość ustawiająca/zwracająca liczbę elementów 8
kolekcji.
Programowanie w języku C#. Maciej Kusy, mkusy@prz.edu.pl
Kolekcja typu kolejka (Queue)
Klasa Queue reprezentuje kolekcję typu kolejka
(FIFO: ang: First In First Out): pierwszy wchodzi pierwszy wychodzi.
Tak jak ArrayList, klasa Queue daje możliwość pracy nad obiektami typu Object, dzięki temu obiekty kolejki
mogą zawierać instancje dowolnego typu.
Zawarta w przestrzeni nazw: System.Collections.
9
Programowanie w języku C#. Maciej Kusy, mkusy@prz.edu.pl
Wybrane składowe klasy Queue
• void Enqueue(Object o) – metoda, która dodaje
obiekt o na koniec kolejki.
• Object Dequeue() – metoda usuwająca (i zwracająca)
obiekt o z kolejki (pierwszy na czele kolejki).
• Object Peek() – metoda, która zwraca obiekt
znajdujący się na przedzie kolejki.
• Object[] ToArray() – metoda kopiująca wszystkie
elementy kolejki do nowej tablicy.
• void Clear() – metoda, która służy do usunięcia
wszystkich elementów z kolejki.
• bool Contains(Object o) – metoda sprawdzająca,
czy w kolejce znajduje się obiekt o.
• Count – właściwość zwracająca rozmiar kolejki.
10
Programowanie w języku C#. Maciej Kusy, mkusy@prz.edu.pl
Kolekcja typu stos (Stack)
Klasa Stack reprezentuje kolekcję typu stos
(LIFO: ang: Last In First Out): ostatni wchodzi pierwszy wychodzi.
Analogicznie jak ArrayList oraz Queue, klasa Stack pozwala manipulować obiektami typu Object, dzięki
temu obiekty stosu mogą przechowywać instancje
dowolnego typu.
Zawarta w przestrzeni nazw: System.Collections.
11
Programowanie w języku C#. Maciej Kusy, mkusy@prz.edu.pl
Wybrane składowe klasy Stack
• void Push(Object o) – metoda, która wstawia
obiekt o na szczyt stosu.
• Object Pop() – metoda usuwająca (i zwracająca)
obiekt o ze stosu (pierwszy na szczycie stosu).
• Object Peek() – metoda, która zwraca obiekt
znajdujący się na szczycie stosu.
• Object[] ToArray() – metoda kopiująca wszystkie
elementy stosu do nowej tablicy.
• void Clear() – metoda, która służy do usunięcia
wszystkich elementów ze stosu.
• bool Contains(Object o) – metoda sprawdzająca,
czy na stosie znajduje się obiekt o.
• Count – właściwość zwracająca rozmiar stosu.
12
Programowanie w języku C#. Maciej Kusy, mkusy@prz.edu.pl
Kolekcja typu słownik
Słownik jest kolekcją składającą się z wartości (danych) powiązanych z kluczami. Klucze są wykorzystywane do
określenia właściwego położenia dla danych
przechowywanych w kolekcji.
Słownik udostępniony przez platformę .NET pozwala łączyć
dowolny typ klucza (liczby całkowite, łańcuchy znaków,
obiekty) z dowolnym typem wartości (liczby całkowite,
łańcuchy znaków, obiekty)
Obiekty używane jako klucze muszą udostępniać metody:
GetHashCode() oraz Equals().
13
Programowanie w języku C#. Maciej Kusy, mkusy@prz.edu.pl
Kolekcja typu słownik – przykład
Pytanie: Jak przechowywać numery indeksów 15-tu
studentów o zadanych nazwiskach?
Najprostsze rozwiązanie: użyć tablicę typu int:
int[] indeksy = new int[15];
Dostęp do każdego numeru indeksu można uzyskać poprzez
podanie odpowiedniej liczby z przedziału: 0,…,14.
Wada: dostęp do indeksów studentów za pomocą notacji
tablicowej jest niewygodny: chcąc znaleźć numer indeksu
studenta znając wyłącznie jego nazwisko, należy wiedzieć, na
której pozycji w tablicy indeksy znajduje się ten student.
Rozwiązanie: najlepiej przechować numery indeksów (wartości) połączone z nazwiskami studentów (klucze) w słowniku.
14
Programowanie w języku C#. Maciej Kusy, mkusy@prz.edu.pl
Wersja słownika – klasa Hashtable
• void Add(Object k, Object w) – metoda, która
wstawia wartość w na podstawie klucza k do słownika.
• void Remove(Object k) – metoda usuwająca element
ze słownika na podstawie klucza k.
• void Clear() – metoda, która służy do usunięcia
wszystkich elementów ze słownika.
• bool ContainsKey(Object k) – metoda
sprawdzająca, czy słownik zawiera klucz k.
• Count – właściwość zwracająca ilość elementów w słowniku.
• Keys – właściwość, która zwraca kolekcję kluczy w słowniku.
• Count – właściwość, która zwraca kolekcję wartości w
słowniku.
• [Object k] – właściwość (indekser) modyfikująca wartość na podstawie klucza k.
15
Programowanie w języku C#. Maciej Kusy, mkusy@prz.edu.pl
Mechanizm typów (klas) generycznych
W wersji .NET 2.0 klasy z przestrzeni System.Collections
dostosowano do współpracy z mechanizmem typów
uniwersalnych, co daje większe bezpieczeństwo typów.
Klasy uniwersalne ( ang. generics) zawarte zostały w nowej przestrzeni o nazwie: System.Collections.Generic.
Klasy te umożliwiają tworzenie nowych typów (kontenerów
generycznych) – element Common Type System ( CTS).
Klasy należące do obydwu przestrzeni oferują identyczną
funkcjonalność (choć zmieniono kilka nazw).
Klasy uniwersalne eliminują konieczność rzutowania lub
bezpośredniego sprawdzania typów.
16
Programowanie w języku C#. Maciej Kusy, mkusy@prz.edu.pl
Składnia klas generycznych
Deklaracja klasy dokonywana jest przy użyciu parametru
typu ( ang. type parameter) umieszczonego w nawiasach <> : class Kolekcja<T>
{
}
Kompilator rozpozna wszystkie wystąpienia parametru T i zastąpi je odwołaniami do żądanego typu.
Utworzenie obiektu klasy uniwersalnej:
Kolekcja<Pies> kol = new Kolekcja<Pies> (); Uwaga: Można stosować więcej niż jeden parametr typów.
17
Programowanie w języku C#. Maciej Kusy, mkusy@prz.edu.pl
Ograniczanie parametru typu
Istnieje również możliwość ograniczenia zbioru typów dla
klasy uniwersalnej. Aby tego dokonać, wystarczy dla każdego
parametru typu zdefiniować (opcjonalną) listę ograniczeń:
class Stos<T> where T : class
{}
Trzy specjalne ograniczenia dla parametru typu:
- class – parametr musi być typu referencyjnego,
- struct – parametr musi być typu wartościowego,
- new() – parametr musi zawierać bezparametrowy konstruktor.
Dla każdego parametru typu można zdefiniować wiele
ograniczeń dotyczących interfejsu i po jednym ograniczeniu
dotyczącym klasy.
18
Programowanie w języku C#. Maciej Kusy, mkusy@prz.edu.pl
Klasa generyczna List<T>
Jest generycznym odpowiednikiem klasy ArrayList i
udostępnia analogiczne metody i właściwości.
Rozmiar kolekcji typu List<T> jest dynamicznie zwiększany.
Typ List<T> eliminuje konieczność rzutowania i weryfikacji typów.
W przypadku deklaracji typu generycznego, kompilator
generuje kod dla określonego typu, przez co nie jest
konieczna „zamiana na obiekty” typów prostych (tzw.
pakowanie), tak jak w przypadku klasy ArrayList.
Przykładowe definicje:
List<Pies> lp = new List<Pies> ();
List<string> ls = new List<string> (); 19
Programowanie w języku C#. Maciej Kusy, mkusy@prz.edu.pl
Zestawienie przestrzeni nazw kolekcji
Tabela przedstawia wybrane klasy kolekcji z przestrzeni
System.Collections oraz ich odpowiedniki – typy
generyczne z przestrzeni System.Collections.Generic.
System.Collections System.Collections.Generic
ArrayList
List<T>
Hashtable
Dictionary<K,T>
Queue
Queue<T>
Stack
Stack<T>
20
Programowanie w języku C#. Maciej Kusy, mkusy@prz.edu.pl
Wyrażenia lambda
Wyrażenia lambda są metodami anonimowymi, które mogą
zawierać wyrażenia lub deklaracje.
Wyrażenia lambda używają operatora => w celu
odseparowania zmiennych wejściowych po swojej lewej
stronie od ciała operatora po prawej stronie.
string[] lancuchy = { "Ala", "ma", "kota" }; string literaM = lancuchy.First(x => x.Contains("m")); int[] liczby = { 0, 4, 1, 3, 9, 8, 5, 7, 2, 0 };
var liczbyNieParzyste = liczby.Where(x => x % 2 == 1); foreach (var v in liczbyNieParzyste)
{
Console.Write("{0} ", v);
}
21
Programowanie w języku C#. Maciej Kusy, mkusy@prz.edu.pl
Obiekty typu DataSet i DataTable
DataSet jest głównym komponentem w bibliotece
ADO.NET. Składa się z kolekcji obiektów typu DataTable
zawartych we właściwości Tables.
DataTable jest typem w bibliotece ADO.NET, który reprezentuje pojedynczą tabelę danych w komponencie DataSet.
Tworząc tabelę DataTable należy najpierw stworzyć jej
schemat dodając obiekt typu DataColumn (reprezentujący
kolumny) za pomocą właściwości Columns.
Aby wypełnić tabelę DataTable rekordami konieczne jest
dodanie do niej wierszy poprzez metodę Add kolekcji Rows.
Klasa DataSet umożliwia zapis i odczyt danych w formacie XML (WriteXml(), ReadXml()).
22