Cele przedmiotu
wiedza: Poznanie zasad, narzędzi i zastosowań paradygmatu programowania obiektowego umiejętności: potrafi realizować algorytmy przetwarzania danych przy pomocy języka C# w
środowisku programistycznym MS Visual Studio
Paradygmat[gr. parádeigma ‘wzór’] - ogólnie uznane osiągnięcie naukowe (teoria naukowa), które w pewnym okresie dostarcza modelowych rozwiązań w danej dziedzinie nauki. Inaczej wzór, wzorzec.
Literatura
• Perry S.C. - C# i .NET. Wydawnictwo Helion, 2006
• Liberty J. – Programowanie C#. Wyd. Helion, 2006
• Hejlsberg A., Torgersen M., Wiltamuth S., Golde P. – Język C#. Programowanie.
Wyd. Helion, 2010
• Troelsen A. – Język C# i platforma .NET. Wyd. Mikom, 2006
• Hoffman K. – Visual C# 2005, księga eksperta. Wyd.Helion, 2007
• Liberty J., Hurwitz D., Programowanie ASP.NET. Wyd. HELION, 2007
• Wei-Meng Lee – C# 2008. Warsztat programisty. Wyd. Helion 2010
1 Ogólna charakterystyka środowiska MS Visual Studio i języka programowania C#
2 Różnice pomiędzy językiem C++ a C#
Struktura programu w języku C#. Program jako obiekt klasy Application 3 "Anatomia i fizjologia" klas i obiektów
4 Hermetyzacja, dziedziczenie i polimorfizm w języku C#
5 Biblioteki klas i ich wykorzystanie do tworzenia programów użytkowych
6 Wykorzystanie bibliotek Windows Forms do tworzenia aplikacji "okienkowych" (GUI)
Tematyka wykładu
Tematyka laboratorium
1 Środowisko API - MS Visual Studio - podstawowe funkcje, nawigacja, kompilacja i debuggowanie programów
2 Tworzenie i testowanie prostych programów konsolowych w języku C#
3 Tworzenie i użycie własnych typów danych - klas
4 Wykorzystanie elementów bibliotek klas – w tym Windows Forms - do tworzenia prostych programów użytkowych
Formy dydaktyczne:
-Wykład
-Laboratorium –
Zaliczenie kursu na stopień.
Na ocenę dostateczną Na ocenę dobrą Na ocenę bardzo dobrą Student potrafi poprawnie
zaprojektować strukturę programu użytkowego do rozwiązania zadania.
Ponadto student potrafi dobrać klasy oraz
zaproponować i zdefiniować własne klasy, ich właściwości i metody składające się na rozwiązanie zadania.
Ponadto student potrafi zaplanować i przeprowadzić
procedury testowania rozwiązania zadania.
Kryteria oceny:
• Elementy składowe aplikacji tzw. "okienkowej" (GUI)
• Charakterystyka języka C#
• Język C# i środowisko IDE
• Struktura przykładowej aplikacji w języku C#
Elementy składowe aplikacji
Podstawowymi elementami, z których buduje się aplikacje są:
- formularze,
- obiekty (komponenty),
- zdarzenia.
W aplikacjach wykorzystujących elementy interfejsu graficznego (GUI) formularz jest klasą czyli typem zdefiniowanym przez programistę.
Konsekwencje:
1. Formularz jest typem danych, a nie obiektem danych. Jeden z obiektów formularzy składających się na
aplikację jest formularzemgłównym. Tworzy go automatycznie system w momencie uruchomienia programu służy on jakookienko inicjacyjne.
2. Można utworzyć wiele obiektów tego samego typu formularza.
3. Każda klasa formularza ma związane ze sobą własności. Dotyczą one postaci formularza widocznego na ekranie (kolor, wielkość); mają wpływ na zachowanie – np. określają, czy wielkość formularza można zmieniać dynamicznie. Wartości początkowe własności formularza określamy w czasie tworzenia projektu formularza.
Zestaw wartości początkowych jest używany zawsze wtedy, gdy program tworzy nowy obiekt klasy formularz. W czasie działania programu wartości niektórych własności można zmieniać.
4. Każda klasa formularza ma zbiór związanych z niąmetod. Metoda jest funkcją, dzięki której można wykonać określoną akcję z użyciem formularza (określa "zachowanie"). Przykładowo - formularz ma metody
sprawdzania zmian własności formularza.
5. Twórca aplikacji – programista może do klasy formularza dodać własne metody. Jest to przydatne wtedy, gdy chcemy zdefiniować procedurę, która może być użyta przez inną funkcję wewnątrz klasy lub gdy chcemy zapewnić kontrolowany dostęp do klasy z obiektów znajdujących się poza klasą.
Można tworzyć również aplikacje działające w tzw. „trybie konsolowym” (właściwym dla systemu DOS), nie angażując mechanizmów interface graficznego.
Komponenty(kontrolki) to obiekty z bogatej biblioteki klas lub klas definiowanych przez programistę, które umieszcza się na formularzu i za ich pomocą użytkownik może sterować pracą aplikacji.
Niektóre kontrolki pracują "w tle", są niewidoczne w czasie działania aplikacji. Każda klasa reprezentująca kontrolkę ma swój, specyficzny zestaw właściwości, np. położenie na ekranie, wielkość, kolor tła itp. Ich wartości początkowe ustala twórca aplikacji w fazie projektowania niektóre z nich można zmieniać dynamicznie jako np.
reakcję na określonezdarzenia (w ramach "obsługi zdarzeń").
Sterowanie wykonywaniem aplikacji działającej pod kontrolą systemu operacyjnego Windows odbywa się w sposób odmienny niż ten, do którego przywykliśmy w przypadku tworzenia i działania aplikacji "konsolowych".
System operacyjny reaguje na każdą zmianę stanu otoczenia działającej aplikacji (np. "kliknięcie" kontrolki klawisza na formularzu, zmiana położenia kursora na ekranie, naciśnięcie przycisku klawiatury) rozesłaniem do wszystkich procesów komunikatu ozdarzeniu. Każda klasa obiektu ma określony zestaw komunikatów, na które może zareagować. Programista w fazie tworzenia aplikacji wybiera te zdarzenia - komunikaty systemu operacyjnego, które aplikacja powinna obsłużyć i pisze kod źródłowy odpowiedniej metody.
Charakterystyka języka C# i środowiska IDE
Literatura: Liberty J., Programowanie C#. Wyd.Helion, Gliwice, 2006 lub nowsze
Platforma .NET
– zestaw języków programowania:
C++, C#, Visual Basic, Visual J#, Jscript.NET i zestaw narzędzi programistycznych Visual Studio .NET, biblioteka klas i
środowisko uruchomieniowe CLR (Common Language Routine) do wykonywania programów przeznaczonych na tą platformę - dwie generacje serwerów .NET Enterprise
- nowe urządzenia przystosowane do platformy .NET (urządzenia mobilne, konsole do gier itp.).
Wykonywanie programów na platformie .NET możliwe jest po zainstalowaniu w systemie mechanizmu .NET Framework.
Jego najważniejszym elementem jest środowisko uruchomieniowe CLR, które składa się z tzw. „maszyny wirtualnej” (podobnej do VM Javy). CLR tworzy obiekty,
przydziela im pamięć, sprawdza bezpieczeństwo, wykonuje polecenia i odzyskuje pamięć.
Jego częścią jest wspólny dla języków programowania system typów.
Kompilator programów na platformę NET nie tworzy plików
wykonywalnych – przekłada źródła na ciągi instrukcji standardowego języka pośredniego MSIL (Microsoft Intermediate Language).
Dopiero w środowisku CLR następuje ich przekształcenie na kod maszynowy i wykonanie.
Kompilacja kodu źródłowego na kod pośredni następuje w czasie budowy projektu. Kod pośredni zostaje zapisany na dysku w pliku .exe
(nie należy go mylić z plikiem wykonywalnym w innych systemach programowania).
W momencie uruchomienia programu następuje ponowna kompilacja programu – tzw. "kompilacja w locie" (JIT - Just In Time).
W wyniku kompilacji JIT powstaje kod maszynowy, który wykonuje
procesor maszyny.
Charakterystyka języka C#
- prosty bo zawiera tylko około 80 słów kluczowych (?) i kilkanaście wbudowanych typów,
- zestaw operatorów i instrukcji podobny do C++, reguły składni, leksykalne itp.
również zbliżone do C++,
-programy w C# budowane są z obiektów klas z bogatej biblioteki oraz z obiektów klas "własnych” programisty,
-wszystkie elementy klasy znajdują się w jej deklaracji, niepotrzebne są pliki nagłówkowe ani pliki definicji interfejsu,
-możliwe jest automatyczne tworzenie dokumentacji projektu z wykorzystaniem
notacji XML
/* Projekt 1 - przeliczanie lat swietlnych na miliony kilometrow */
using System; // 1 class LataSwietlne // 2 {
public static void Main() // 3 {
double lata, km; // 4
double prędkość_światła = 0.3; // 5 w mln km na sekundę string str; // 6
Console.Write("Podaj odleglość w latach świetlnych: "); // 7 str = Console.ReadLine(); // 8
lata = Double.Parse(str); // 9 Można to tak:
// lata = Double.Parse(Console.ReadLine())
km = prędkość_światła * lata * 365.0 * 24.0 * 3600.0; // 10
Console.WriteLine("Odległość w mln kilometrow = " + km); // 11 Console.WriteLine("Naciśnij klawisz ENTER..."); // 12
Console.Read(); // 13
} // 14
} // 15
Znaczenie poszczególnych linii:
1. W tym miejscu system programowania umieszcza automatycznie listę tzw. przestrzeni nazw; są to po prostu nazwy bibliotek klas, z których korzystamy tworząc obiekty naszego programu
2. Nagłówek deklaracji/definicji klasy o nazwie LataSwietlne
3.Nagłówek metody (funkcji) głównej – od niej rozpoczyna się wykonywanie aplikacji 4. Deklaracja zmiennych typu double – jest to typ "wbudowany" w język (struktura)
5. Deklaracja i inicjacja zmiennej typu double – w języku C# w nazwach zmiennych mogą występować znaki alfabetu narodowego
6. Deklaracja obiektu klasy string
7. Wyświetla na ekranie monitora napis; w C# do komunikacji ze standardowymi urządzeniami zewnętrznymi wykorzystuje się metody statyczneklasy Console; tutaj metoda Write wyświetli na ekranie monitora napis, którego treść jest jej argumentem
8. Metoda ReadLine wywołana na rzecz klasy Console zwraca łańcuch znaków (napis) wprowadzony do bufora
klawiatury, zakończony znakiem nowej linii – wczytuje więc całą linię tekstu i przypisuje ją zmiennej, której nazwa znajduje się po lewej stronie operatora przypisania =
9. Struktura Double (w C# struktury reprezentują wbudowane typy danych – np. typ podwójnej precyzji), posiada m.in.
metodę Parse, jej argumentem jest łańcuch znaków; metoda ta dokonuje konwersji napisu na daną liczbową odpowiedniego typu
10. Po prawej stronie operatora przypisania znalazło się wyrażenie arytmetyczne, jego obliczona wartość zostanie przypisana zmiennej, której nazwa znajduje się po lewej stronie znaku = (zasada identyczna jak w przypadku innych języków
programowania, np. C czy C++)
11. Metoda WriteLine klasy Console wyświetli na ekranie monitora napis, który jest jej argumentem; na uwagę
zasługuje zaskakująca postać argumentu – operator + w tym kontekście działa w ten sposób, że dokonuje konwersji wartości liczbowej (wartość zmiennej km) na łańcuch znaków i łączy go z pierwszą częścią napisu; po wyświetleniu kursor przechodzi na początek nowej linii
12. J.w.
Podstawowe typy danych Typy liczbowe i znakowe
W C/C++ istnieją typy danych nazywane typami prostymi (inaczej typy "wbudowane") dla odróżnienia od typów strukturalnych (tablice, struktury, klasy).
W języku C# - tzw. typy proste są strukturami, a słowa kluczowe znane z C/C++, takie jak int, double itp. są aliasami (nazwami zastępczymi) do nazw tych struktur.
Np. stała typu int o wartości 1, jest instancją (egzemplarzem) struktury o nazwie System.Int32 i udostępnia wszystkie jej metody.
Poprawny jest zatem przykładowy ciąg instrukcji:
int i = 10;
string s = i.ToString();
Metoda ToString przekształca wartośćzmiennej w ciąg znaków o formacie właściwym dla danego typu
Kategoria Opis
Typy wartościowe Typy proste Całkowite ze znakiem: sbyte, short, int, long Całkowite bez znaku: byte, ushort, uint, ulong Znaki unicode: char
Zmiennoprzecinkowe: float, double Dziesiętne wysokiej precyzji: decimal Boole'owskie: bool
Typy wyliczeniowe Definiowane przez użytkownika w postaci enum E {...}
Struktury Definiowane przez użytkownika w postaci struct S {...}
Typy dopuszczające wartość pustą
Rozszerzenia wszystkich innych typów wartościowych o wartość null
Typy referencyjne Klasy Ostateczna klasa bazowa wszystkich innych typów: object Łańcuchy Unicode: string
Definiowane przez użytkownika w postaci classC {...}
Interfejsy Definiowane przez użytkownika w postaci interface I {…}
Tablice Jedno- i wielowymiarowe, na przykład int []i int [,]
Delegacje Definiowane przez użytkownika w postaci na przykład delegate int D(…)
Tabela 1.1. Typy danych w C#
Tabela 1.2. Typy proste w C# - miejsce zajmowane w pamięci i zakresy wartości:
Nazwa typu (słowo kluczowe,
alias klasy)
Klasa z przestrzeni nazw System
Liczba zajmowanych bitów
Zakres wartości Wartość
domyślna
bool Boolean true, false false
sbyte SByte 8 bitów ze znakiem Od -128 do 127 0
byte Byte 8 bitów bez znaku Od 0 do 255 0
short Int16 2 bajty ze znakiem Od -32 768 do 32 767 0
int Int32 4 bajty ze znakiem Od -2 147 483 648 Do 2 147 483 647
0
long Int64 8 bajtów ze znakiem Od -9 223 372 036 854 775 808 Do 9 223 372 036 854 775 807
0L
ushort UInt16 2 bajty bez znaku maks. 65 535 0
uint UInt32 4 bajty bez znaku maks. 4 294 967 295 0
ulong UInt64 8 bajtów bez znaku maks. 18 446 744 073 709 551 615 0L
char Char 2 bajty Znaki Unicode od 0 do 65535 ‘\0’
float Single 4 bajty (zapis
zmiennoprzecinkowy)
Najmniejsza bezwz. 1.4 *10-45 Największa ok. 3.403 * 1038
0.0F
-324
Konwersje typów podstawowych
Oprócz możliwości wykonywania w kodzie C# tzw. jawnej konwersji typów (za pomocą operatora rzutowania) można doprowadzić do tzw. niejawnej konwersji typów (konwersji domyślnej).
Ze względów bezpieczeństwa możliwa jest tylko konwersja niejawna z typu całkowitego na typ zmiennoprzecinkowy (ogólnie na typ o większej precyzji) oraz z typu o mniejszym zakresie wartości na typ o większym zakresie.
Konwersja w drugą stronę – ponieważ jej konsekwencją jest utrata informacji wymaga zastosowania operatora rzutowania.
Przykładowo próba przypisania wartości typu double do zmiennej typu int spowoduje
sygnalizację błędu.
Typy wartościowe i referencyjne
Język C# jest konsekwentnie obiektowy - obiektami są nawet stałe liczbowe.
Z faktu, że wszystko jest w C# obiektem, nie wynika wcale, że wszystkie typy obiektów są klasami.
Nie wszystkie obiekty są w C# instancjami klas - oprócz klas istnieją także struktury.
W C# struktura, tak jak w C++, może mieć nie tylko pola, ale także metody. Ograniczeniem struktur w stosunku do klas jest zakaz dziedziczenia zarówno ze zdefiniowanych struktur, jak i dziedziczenia przez struktury.
Struktury mogą natomiast implementować interfejsy.
Jednak najważniejsza różnica między klasami a strukturami pojawia się przy próbie stworzenia obiektu będącego instancją klasy lub struktury.
Obiekt będący instancją klasy należy utworzyć za pomocą operatora new.
Obiekt tak utworzony znajdzie się w obszarze pamięci nazywanym stertą (ang. heap).
(1) Int32 i; lub int i;
(2) Button b;
(3) Int32 i = new Int32(); lub int i = new int();
(4) Button b = new Button();
Ponieważ System.Web.UI.WebControls.Button jest klasą, wyrażenie (2) jest jedynie deklaracją zmiennej b, która jest niezainicjowaną referencją do obiektu typu Button.
Aby powstał obiekt - instancja klasy, musimy użyć operatora new, czyli umieścić w kodzie polecenie (4).
Obiekty - instancje struktur możemy tworzyć deklarując je.
Polecenie (1) tworzy obiekt w obszarze pamięci nazywanym stosem(ang. stack).
Obiekt ten jest utożsamiany ze zmienną i.
Jeżeli nie użyjemy operatora newdo wywołania konstruktora struktury, to pola tak
stworzonego obiektu pozostaną niezainicjowane i obiekt taki nie może być użyty, tj. nie może być argumentem metody (poza metodami wymuszającymi przypisanie modyfikatorem out) ani operatorów poza operatorem przypisania z lewej strony.
W przypadku struktur implementujących typy liczbowe inicjacja możliwa jest za pomocą stałej liczbowej np. Int32 i = 1; (1 jest też formalnie obiektem), lub przez użycie operatora new.
W przypadku użycia instrukcji typu (3) konstruktor domyślny inicjuje pola obiektu zerami, wartościami false lub null odpowiednio do ich typu.
W celu utworzenia instancji struktury można użyć również przeciążonego konstruktora, który pozwala zainicjować pola struktury wartościami innymi niż domyślne, np.:
Int32 i = new Int32(1);
Operatory działające na strukturach zdefiniowano w taki sposób, że operują na stanie obiektu (wartości liczby).
W języku C# - inaczej niż w C++ o wyborze miejsca gdzie tworzony jest obiekt (stos albo sterta) decyduje nie sposób jego utworzenia a typ.
Z podziałem na struktury i klasy wiąże się jeszcze jedno rozróżnienie, a mianowicie podział na zmienne wartościowe oraz zmienne referencyjne.
Używanie w C# trzeciego, dostępnego (ze względów historycznych) typu zmiennych —
wskaźników, jest oznaką „złego gustu” programisty. Taka aplikacja wymaga specjalnego
Zmienne typów wartościowych utożsamiane są z instancjami (egzemplarzami) struktur znajdującymi się na stosie.
Zmienne typów referencyjnych to referencje (wskaźniki) do instancji klas, które powstają na stercie.
Utożsamienie zmiennej wartościowej z obiektem, który reprezentuje, jest całkowite.
Polecenie kopiowania wartości int j = i;
tworzy nowy obiekt j na stosie o wartości skopiowanej z i.
W przypadku zmiennych referencyjnych łatwo jest odseparować sam obiekt i wskazującą na niego referencję.
Kopiowanie referencji powoduje jedynie stworzenie nowej zmiennej wskazującej na ten sam obiekt:
Button a = b;
"Zmienna” a zawiera adres wskazujący na obiekt b.
Łańcuchy (napisy)
W C# klasa System.String (alias string) implementuje napisy (łańcuchy) co znacznie ułatwia ich przetwarzanie.
W klasie string zdefiniowano np. przeciążony operator + który pozwala łączyć łańcuchy.
Najczęściej używane metody i właściwości klasy System.String przedstawiono w tabeli 1.3.
Listing 1.2 ilustruje działanie metod zebranych w tej tabeli.
W klasie System.Stringzdefiniowano przeciążone operatory dodawania + oraz +=, za pomocą których możemy łączyć ze sobą łańcuchy.
Przykład działania tego operatora pokazano na zamieszczonym dalej listingu 1.3.
W klasie System.String zdefiniowano również metodę Split, której argumentem jest tablica ograniczników. Metody tej nie wymieniono jej w tabeli 1.3.
Metoda Split dzieli łańcuch na podłańcuchy według ograniczników przekazanych w tablicy. Zwraca tablicę
indeksator [] Zwraca znak na wskazanej pozycji "Polkowice"[3] to 'k'
bool Equals(string) Porównuje łańcuch z podanym w argumencie "Polkowice".Equals("Wrocław") zwróci false
int IndexOf(char), int IndexOf(string)
Zwraca pierwsze położenie litery lub łańcucha (-1 jeżeli nie znalazła)
"Polkowice".IndexOf('k') zwróci 3
int LastIndexOf(char), int LastIndexOf(string)
Zwraca ostatnie położenie litery lub znaku (-1 jeżeli nie ma)
"Polkowice".LastIndexOf('o') zwróci 4
int Length Zwraca długość łańcucha (właściwość) "Polkowice".Length zwróci 9 string Replace(string,
string)
Zamienia wskazany fragment tekstu (I argument) innym (II argument)
"Polkowice".Replace("ol", "a") zwróci "Pakowice"
string Substring(int,int) Zwraca fragment łańcucha od pozycji wskazanej I argumentem o długości równej argumentowi II
"Polkowice".Substring(3,3) zwróci "kow"
string Remove(int,int) Usuwa fragment łańcucha "Polkowice".Remove(3,1) zwróci "Polowice"
string Insert(int, string) Wstawia łańcuch przed znakiem na podanej pozycji
"Polkowice".Insert(3,"a") zwróci "Polakowice"
string ToLower() string ToUpper()
Zmienia wielkość wszystkich liter "Polkowice".ToUpper() zwróci "POLKOWICE"
string Trim(), string TrimStart(), string TrimEnd()
Usuwa spacje z przodu i z tyłu łańcucha " Polkowice ".Trim() zwróci "Polkowice"
string PadLeft(int, char), string PadRight(int, char)
Uzupełnia łańcuch znakiem podanym jako II argument do osiągnięcia podanej długości
"Polkowice".PadLeft(11,'*') zwróci "**Polkowice"
bool EndsWith(string), bool StartsWith(string)
Sprawdza, czy łańcuch kończy się lub rozpoczyna podanym fragmentem
"Polkowice".EndsWith("ce") zwróci true
Listing 1.2
Listing 1.3
Listing 1.4
Operator dodawania (+ +=) w klasie string działa w ten sposób, że każde
kolejne takie działanie tworzy nową kopię łańcucha, tzn. wszystkie cztery instrukcje (listing 1.4) stanowiące ciało pętli powtarzają się dla każdego fragmentu łańcucha źródłowego.
Klasa System.Text.StringBuilder służy do tworzenia i modyfikowania łańcuchów znaków. Jej użycie pozwala wyeliminować niedogodności związane z tworzeniem każdorazowo kopii modyfikowanego łańcucha.
W przykładzie tym użyto pętli foreach (specyficznej dla języka C#), która służy do przeglądania kolekcji obiektów.
Najważniejsze składowe klasy System.Text.StringBuilder przedstawiono
w tabeli 1.4.
Tabela 1.4. Najważniejsze składowe klasy StringBuilder
Metoda Działanie
Chars Mechanizm indeksowania
Length Przypisuje lub zwraca długość obiektu StringBuilder Append() Przeciążona metoda publiczna, która dodaje łańcuch znaków
na koniec aktualnego obiektu StringBuilder
AppendFormat() Przeciążona metoda publiczna, która zamienia specyfikatory formatu aktualnego łańcucha na sformatowaną wartość obiektu
Insert() Przeciążona metoda publiczna, która wstawia łańcuch znaków podany jako jej argument na określoną pozycję obiektu
Remove() Usuwa określone znaki
Replace() Przeciążona metoda publiczna, która zamienia wszystkie
wystąpienia danych znaków na nowe znaki
Listing 1.5