Podstawy programowania Podstawy C Sowa kluczowe we wszystkich

  • Slides: 104
Download presentation
Podstawy programowania Podstawy C#

Podstawy programowania Podstawy C#

Słowa kluczowe – we wszystkich językach programowania wysokiego poziomu – zbiór słów zastrzeżonych, których

Słowa kluczowe – we wszystkich językach programowania wysokiego poziomu – zbiór słów zastrzeżonych, których nie można "przedefiniować", m. in. : • abstract, as, base, bool, break, byte, case, catch, char, class, const, continue, decimal, default, double, else, enum, event, false, float, foreach, if, int, interface, internal, long, namespace, new, null, object, operator, out, override, private, protected, public, readonly, ref, return, sbyte, short, sizeof, static, string, struct, switch, this, throw, true, try, typeof, uint, ulong, ushort, using, virtual, void, volatile, while

Słowa kluczowe – we wszystkich językach programowania wysokiego poziomu – zbiór słów zastrzeżonych, których

Słowa kluczowe – we wszystkich językach programowania wysokiego poziomu – zbiór słów zastrzeżonych, których nie można "przedefiniować", m. in. : • … • Łatwo rozpoznawalne: using System; namespace Pod. Pro. Lab 1 { class Program { Console. Read. Key(true); } }

Słowa kluczowe kontekstowe Słowa, które są lub nie są kluczowe, zależnie od kontekstu; Nie

Słowa kluczowe kontekstowe Słowa, które są lub nie są kluczowe, zależnie od kontekstu; Nie są zastrzeżone, można użyć np. do nazwania zmiennych: • add, alias, async, await, by, descending, dynamic, equals, from, get, global, group, into, join, let, nameof, on, orderby, partial, remove, select, set, value, var, when, where, yield

Nazwy Zasady formalne: • Może zawierać litery, cyfry oraz znak podkreślenia "_" (tzw. podłoga),

Nazwy Zasady formalne: • Może zawierać litery, cyfry oraz znak podkreślenia "_" (tzw. podłoga), można używać znaków diakrytycznych, • Małe i wielkie litery SĄ rozróżniane • Nie może zaczynać się od cyfry • Nie może być słowem kluczowym Int 32 gałąź_numer_3; // ok licznik, LICZNIK; // ok, 3 różne nazwy! 2 pi; // błąd! event; // błąd! Słowo kluczowe

Nazwy Zasady nieformalne: • Klasy, pola, metody, stałe – konwencja Pacal, nazwy klas i

Nazwy Zasady nieformalne: • Klasy, pola, metody, stałe – konwencja Pacal, nazwy klas i pól – rzeczowniki, metod – czasowniki: Dane. Wykresu (klasa – należy unikać nazw na "I") Kolor. Linii (pole) Zapisz. Dane (metoda) • Interfejsy – Pascal poprzedzone literą "I" ISortable • Zmienne lokalne i parametry funkcji – camel. Case: promień pole. Koła

Nazwy Zasady nieformalne: • Nazwy powinny być znaczące: p, k, pole. Koła, kolor. Linii

Nazwy Zasady nieformalne: • Nazwy powinny być znaczące: p, k, pole. Koła, kolor. Linii Kod powinien być czytelny, kiedy do niego zajrzeć po kilku miesiącach albo dla innego programisty (tzw. samodokumentujący się) • Język angielski czy polski? Odpada argument z kaleczeniem języka polskiego => reguły zespołu lub indywidualne preferencje

Styl Środowisko formatuje wg reguł klasycznych: • Nawias "{" i "}" zawsze w nowej

Styl Środowisko formatuje wg reguł klasycznych: • Nawias "{" i "}" zawsze w nowej linii, "else" w nowej linii, wcięcia odpowiadające głębokości zagnieżdżenia • Automatyczne formatowanie – po zakończeniu pisania instrukcji (po wpisaniu "; " lub ostatniego "}"), o ile nie ma błędów; Nie ma re-formatowania po zmianach • Na żądanie (Edit > Advanced > Format Document) Np. dla takiego kodu… if (x>0) {for (i=0; i<3; i++) {z += t[i]; } } else {z = 0; }

Styl Środowisko formatuje wg reguł klasycznych: • Nawias "{" i "}" zawsze w nowej

Styl Środowisko formatuje wg reguł klasycznych: • Nawias "{" i "}" zawsze w nowej linii, "else" w nowej linii, wcięcia odpowiadające głębokości zagnieżdżenia: if (x > 0) { for (i = 0; i < 3; i++) { z += t[i]; } } else { z = 0; }

Styl Alternatywne reguły formatowania, np. : • Nawias "{" na końcu linii, "}" w

Styl Alternatywne reguły formatowania, np. : • Nawias "{" na końcu linii, "}" w nowej linii, "else" razem z "}" (bardziej zwarty): if (x > 0) { for (i = 0; i < 3; i++) { z += t[i]; } } else { z = 0; } - można ustawić w opcjach edytora

Styl Komentarze służą do dokumentowania kodu • Komentarz liniowy – od "//" do końca

Styl Komentarze służą do dokumentowania kodu • Komentarz liniowy – od "//" do końca linii // Jedna linia wyjaśnienia kod… • Komentarz blokowy – od "/*" do "*/" /* Kilka linii wyjaśnienia */ kod…

Styl Komentarze służą do dokumentowania kodu • … • Sekwencja "///" powoduje wstawienie szablonu

Styl Komentarze służą do dokumentowania kodu • … • Sekwencja "///" powoduje wstawienie szablonu dokumentacji XML, który jest czytany przez intellisense /// <summary> /// </summary> /// <param name="a"></param> /// <param name="b"></param> /// <returns></returns> static Int 32 NWD(Int 32 a, Int 32 b) { }

CTS Wspólny system typów CTS (Common Type System) Obiekt Klasa Typy proste Interfejs Typy

CTS Wspólny system typów CTS (Common Type System) Obiekt Klasa Typy proste Interfejs Typy wyliczeniowe Tablica Struktury Typy referencyjne Typy wartościowe

CTS Typy wartościowe • Deklaracja deklarowany (tworzony) jest obiekt Int 32 x; x =

CTS Typy wartościowe • Deklaracja deklarowany (tworzony) jest obiekt Int 32 x; x = 7; • Przypisanie obiekt jest kopiowany Int 32 a, b; a = 13; b = a; (są dwa obiekty Int 32, oba zawierają wartość 13)

CTS Typy referencyjne • Deklaracja deklarowana (tworzona) jest referencja, obiekt nie istnieje dopóki nie

CTS Typy referencyjne • Deklaracja deklarowana (tworzona) jest referencja, obiekt nie istnieje dopóki nie zostanie utworzony operatorem new Button b 1; b 1 = new Button(); • Przypisanie kopiowany jest nie obiekt, tylko referencja do niego Button b 2; b 2 = b 1; (jest jeden obiekt Button, obie referencje wskazują na niego)

Typy proste C# Typ wspólny i rzutowanie • Wszystkie mają wspólny typ bazowy "object"

Typy proste C# Typ wspólny i rzutowanie • Wszystkie mają wspólny typ bazowy "object" – zmienną każdego typu (w tym typu prostego) można przypisać do zmiennej typu object; Odwrotne przypisania wymaga rzutowania (konwersji typów): Int 32 x; object o; x = 13; o = x; x = (Int 32)o; // ok Double y; y = (Double)o; // błąd! (obiekt w "o" nie jest Double)

Typy proste C# Typy proste • Służą do przechowywania pojedynczych wartości logicznych, liczb, znaków,

Typy proste C# Typy proste • Służą do przechowywania pojedynczych wartości logicznych, liczb, znaków, łańcuchów znaków • Wszystkie są strukturami BCL (Base Class Library), wspólne dla. NET; Struktury dostarczają wielu użytecznych metod i stałych, np. dla Int 32: – Int 32. Parse – metoda statyczna, konwertuje łańcuch na liczbę Int 32 – Int 32. Max. Value – stała, maksymalna wartość Int 32 – Int 32. To. String – metoda, konwertuje liczbę Int 32 na łańcuch • Mają aliasy w postaci słów kluczowych, np. – – Int 32 – int Single – float Double – double Boolean – bool (aliasy są zapożyczone z C/C++/Java)

Typy proste C# Typy proste • Wartości logiczne: – Boolean (bool) • Liczby całkowite:

Typy proste C# Typy proste • Wartości logiczne: – Boolean (bool) • Liczby całkowite: – – Byte (byte), SByte (sbyte) Int 16 (short), UInt 16 (ushort) Int 32 (int), UInt 32 (uint) Int 64 (long), UInt 64 (ulong) • Liczby zmiennoprzecinkowe – Single (float) – Double (double) – Decimal (decimal) • Znaki i łańcuchy znaków unicode (tzw. widestring) – Char (char) – String (string)

Typy proste C# Boolean • Wartości logiczne – true i false (są to słowa

Typy proste C# Boolean • Wartości logiczne – true i false (są to słowa kluczowe); Do zmiennej Boolean można wstawić wyłącznie stałą (jw. ) albo rezultat operacji lub funkcji (metody), o ile jest typu Boolean niski. Indeks = indeks < 0. 25 D; Boolean sukces = Int 32. Try. Parse("100", out liczba); • Nie jest dopuszczalna konwersja z wartości liczbowych i odwrotnie (co jest typowe dla języków C/C++): Boolean test; test = (Boolean)1; // błąd! Int 32 number; number = (Int 32)true; // błąd! Obowiązuje również dla warunków, np. w instrukcji warunkowej Int 32 x = 7, y = 0; if (x) y = 2 * x; // błąd! (ale w C++ ok)

Typy proste C# Liczby całkowite: • Wyróżniamy 8 odmian; różnią się obecnością znaku oraz

Typy proste C# Liczby całkowite: • Wyróżniamy 8 odmian; różnią się obecnością znaku oraz ilością zajmowanego w pamięci miejsca (1, 2, 4 i 8 bajtów, tj. 8, 16, 32 i 64 bity) a w konsekwencji zakresem wartości – – Byte (byte), SByte (sbyte) Int 16 (short), UInt 16 (ushort) Int 32 (int), UInt 32 (uint) Int 64 (long), UInt 64 (ulong)

Typy proste C# Liczby całkowite: • Zakres wartości wynosi od -2 n-1 do 2

Typy proste C# Liczby całkowite: • Zakres wartości wynosi od -2 n-1 do 2 n-1 -1 dla wersji ze znakiem oraz od 0 do 2 n-1 dla wersji bez znaku, np. : – – – SByte: -128. . 127, Byte 0. . 255 Int 16: -32. 768. . 32. 767, UInt 16: 0. . 65. 535 Int 32: -2. 147. 483. 648. . 2. 147. 483. 647 Uint 32: 0. . 4, 294, 967, 295 Int 64: ± 9, 223, 372, 036, 854, 775, 807 UInt 64 0. . 18, 446, 744, 073, 709, 551, 615 ± 32000, 0. . 65000 ± 2 miliardy 0. . 4 miliardy ± 9 e 18 0. . 18 e 18 Operacje arytmetyczne (np. "+") są wykonywane na Int 32 lub Int 64; po dodaniu dwóch zmiennych Int 16 trzeba dokonać jawnej konwersji wyniku – niepraktyczne, lepiej używać Int 32 Int 16 x=1, y=2; Console. Write. Line((x). Get. Type()); // x jest Int 16 Console. Write. Line((+x). Get. Type()); // +x to już Int 32 Console. Write. Line((x+y). Get. Type()); // x+y też Int 32

Typy proste C# Liczby zmiennoprzecinkowe • Single (float), 32 bity – Zakres wartości: 0,

Typy proste C# Liczby zmiennoprzecinkowe • Single (float), 32 bity – Zakres wartości: 0, ± 1. 5 e− 45. . ± 3. 4 e 38, ±nieskończoność, nie-liczba – 7 cyfr znaczących • Double (double), 64 bity – Zakres wartości: 0, ± 5. 0 e− 324. . ± 1. 7 e 308 , ±nieskończoność, nie-liczba – 15 cyfr znaczących • Decimal (decimal), 128 bitów – Zakres wartości: 0, ± 1. 0 e-28. . ± 7. 9 e 28 – 28 cyfr znaczących Single i Double, po przekroczenia zakresu wartości podczas obliczeń, otrzymają wartość 0 lub ±∞, a ostatecznie Na. N (np. 0/0, 0*∞); Decimal bardziej tradycyjnie wygeneruje wyjątek programowy; Decimal ma mniejszy zakres wartości przy większej precyzji - do specyficznych zastosowań, np. obliczeń finansowych

Typy proste C# Znaki i łańcuchy • Do zapisu znaków używany jest Unicode (1

Typy proste C# Znaki i łańcuchy • Do zapisu znaków używany jest Unicode (1 znak = 2 bajty, UInt 16), łańcuchy to sekwencje znaków – Char (char) – String (string) W Unicode mieszczą się znaki wszystkich "żywych" alfabetów Unicode eliminuje kłopoty ze znakami diakrytycznymi, używaniem stron kodowych itp. • Obie struktury są wyposażone w liczne metody – większość zadań związanych z przetwarzaniem znaków i łańcuchów jest gotowa • W przetwarzaniu znaków i łańcuchów są uwzględniane ustawienia regionalne (tzw. lokalizacja) – domyślnie wg ustawień systemu, ale można to zmienić

Typy proste C# Znaki i łańcuchy • … • W C# łańcuchy są traktowane

Typy proste C# Znaki i łańcuchy • … • W C# łańcuchy są traktowane w specjalny sposób – raz nadana wartość nie może być modyfikowana, zamiast tego tworzona jest nowa struktura (z nową wartością), a stara jest usuwana z pamięci przez GC, zupełnie inaczej niż pozostałe typy proste, w których po prostu zmienia się wartość istniejącej cały czas, tej samej zmiennej. Programy intensywnie przetwarzające łańcuch mogą z tego powodu działać wolniej – każda najmniejsza zmiana wartości łańcucha, choćby jednego jego znaku, powoduje utworzenie nowej struktury i pozbycie się starej. Aby tego uniknąć należy stosować obiekt String. Builder

Typy proste C# Konwersje typów prostych • Konwersja automatyczna jest możliwa, gdy nie ma

Typy proste C# Konwersje typów prostych • Konwersja automatyczna jest możliwa, gdy nie ma ryzyka utraty wartości lub pogorszenia precyzji: Int 32 a; Int 16 b = 77; a = b; // ok, Int 32 <- Int 16 w przeciwnym razie jest błędem składniowym: b = a; Single y; y = 1. 25; // błąd: Int 16 <- Int 32 // błąd: Single <- Double • Można stosować konwersje wymuszone: b = (Int 16) a; Przy przekroczeniu zakresu wartości konwersja nie kończy się błędem, ale wynik może być niespodzianką

Typy proste C# Deklaracja zmiennych • Nazwa typu i lista nazw zmiennych, rozdzielona przecinkami:

Typy proste C# Deklaracja zmiennych • Nazwa typu i lista nazw zmiennych, rozdzielona przecinkami: Int 32 a; Double x, y, z; • Można połączyć deklarację z nadaniem początkowej wartości (może to dotyczyć wszystkich lub tylko wybranych zmiennych): Int 32 a = 7; Double x = 13. 0, y = 0. 0, z; • Może istnieć tylko jedna zmienna o danej nazwie, ponowna deklaracja jest błędem: Int 32 n; Int 32 n = 7; // błąd – zmienna n już istnieje Double n; // też błąd

Typy proste C# Zasięg zmiennej • Zasięg zmiennej lokalnej jest ograniczony do bloku (od

Typy proste C# Zasięg zmiennej • Zasięg zmiennej lokalnej jest ograniczony do bloku (od "{" do "}"), w którym została zadeklarowana. Tym blokiem jest zawsze funkcja, jednak może to być węższy blok: static void Main(string[] args) { Double x; // błąd – zmienna x już istnieje Int 32 n; } n = 7; // błąd – tu już nie ma zmiennej n { Double n; } } // ok. , inny blok, nowa zmienna n

Typy proste C# Stałe liczbowe (szerzej: literały) • Stałe liczbowe maja określony typ –

Typy proste C# Stałe liczbowe (szerzej: literały) • Stałe liczbowe maja określony typ – 12 – Int 32 – 12. 0 albo 1. 2 e 1– Double – 0 x 12 – Int 32, notacja szesnastkowa (=18 dziesiętnie) • Stałe całkowite są niejawnie konwertowane na Byte i Int 16, o ile wartość na to pozwala: Byte b = 500; // błąd! • Aby jawnie określić typ należy stosować sufiksy: – – – U – uint (UInt 32) L – long (Int 64) F – float (Single) D – double (Double) M – decimal (Decimal) Single s = 1. 25; // błąd! 1. 25 F będzie ok Decimal d = 1. 25; // błąd! 1. 25 M będzie ok

Typy proste C# Stałe liczbowe (szerzej: literały) • Stałe znakowe są zapisywane w apostrofach,

Typy proste C# Stałe liczbowe (szerzej: literały) • Stałe znakowe są zapisywane w apostrofach, na kilka sposobów Char a, b, c, a = 'A'; b = 'u 0042'; c = 'x 0043'; d = (Char)68; e = 't'; d, e; // // "B", numer znaku Unicode "C", notacja szesnastkowa "D", konwersja z liczby całkowitej <tab>, tzw. sekwencja ucieczki • Stałe łańcuchowe są zapisywane w cudzysłowach: String s 1, s 2; s 1 = "Hellornworld"; s 2 = @"d: archiwumplik. zip"; Normalnie wykrywane są sekwencje ucieczki: "t" – tabulator, "r" – CR, "n" – LF, "\" – znak "" Użycie "@" wyłącza sekwencje ucieczki – przydatne, gdy w łąńcuchu występują znaki "", np. ścieżkach do plików

Typy proste C# Typy wyliczeniowe • Służą do definiowania zbioru dopuszczalnych wartości enum Color

Typy proste C# Typy wyliczeniowe • Służą do definiowania zbioru dopuszczalnych wartości enum Color { Red, Green, Blue } Color color = Color. Red;

Typy proste C# Typy wyliczeniowe • Można by definiować stałe "luzem", ale grozi to

Typy proste C# Typy wyliczeniowe • Można by definiować stałe "luzem", ale grozi to pomyłkami. Dzięki ścisłej kontroli typów w C#, typy wyliczeniowe gwarantują używanie zawsze poprawnych wartości Np. kolory konsoli i aplikacji okienkowych są liczbami innego typu. Dzięki typom wyliczeniowym nie ma możliwości pomylenia ich: Console. Foreground. Color = Console. Color. Yellow; // ok Label 1. Fore. Color = Color. Yellow; // ok Console. Foreground. Color = Color. Yellow; // błąd // niezgodny typ, komunikat w oknie błędów głosi: // Cannot implicitly convert type 'System. Drawing. Color' // to 'System. Console. Color'

Operatory C# • Podstawowe (primary) x. y f(a) t[n] (lewe) x++ x-- new •

Operatory C# • Podstawowe (primary) x. y f(a) t[n] (lewe) x++ x-- new • Jednoargumentowe +x -x !x ~x (prawe) ++x --x (typ)x • Mnożenia i dodawania * + / - (lewe) % • Przesuwania bitów (lewe) << >> • Relacji i równości < <= > == != >= (lewe) is as • Bitowe i logiczne (lewe) & ^ | && || • Warunkowy (prawe) ? : • Przypisania i rozszerzone przypisania = *= /= %= += -= <<= >>= &= ^= |= (prawe)

Operatory C# • Hierarchia operatorów Określona dla danego języka programowania kolejność wykonywania operatorów w

Operatory C# • Hierarchia operatorów Określona dla danego języka programowania kolejność wykonywania operatorów w wyrażeniu Np. * jest wyżej w hierarchii niż +, więc w wyrażeniu y = a + b * c; najpierw będzie wykonane mnożenie Różne języki programowania mają różne hierarchie operatorów. O ile mnożenie jest we wszystkich językach przed dodawaniem, to operatory logiczne mogą być w hierarchii wyżej (np. Pascal) albo niżej (np. C/C++/Java/C#) niż arytmetyczne Kolejność wynikającą z hierarchii można zmieniać używając nawiasów, wyłącznie "(" i ")", które mogą być zagnieżdżone Y = ((a + b) / (c – d));

Operatory C# • Wiązanie operatorów Określona dla danego języka programowania kolejność wykonywania operatorów o

Operatory C# • Wiązanie operatorów Określona dla danego języka programowania kolejność wykonywania operatorów o tej samej hierarchii Większość operatorów ma wiązanie lewe (są wykonywane od lewej) y = a / b * c; // (a/b)*c; c w liczniku! Tylko operatory przypisania mają wiązanie prawe x = y = z = 7; Kolejność wynikającą z wiązania można zmieniać używając nawiasów, wyłącznie "(" i ")", które mogą być zagnieżdżone y = a / (b * c); // a/(b*c); c w mianowniku

Operatory C# • Operator dostępu: x. y Daje dostęp do metod, pól, właściwości; Wpisanie

Operatory C# • Operator dostępu: x. y Daje dostęp do metod, pól, właściwości; Wpisanie ". " aktywuje Intellisense – widoczność elementów jest zależna od kontekstu, środowisko pamięta też co ostatnio było używane

Operatory C# • Operatory zwiększania i zmniejszania Przyrostkowe operatory ++ oraz -- dostarczają rezultat

Operatory C# • Operatory zwiększania i zmniejszania Przyrostkowe operatory ++ oraz -- dostarczają rezultat PRZED zmianą wartości: Int 32 x = 0, y; y = x++; // y=0, x=1 • Operatory jednoargumentowe zwiększania i zmniejszania Przedrostkowe operatory ++ oraz -- dostarczają rezultat PO zmianie wartości: Int 32 x = 0, y; y = ++x; // y=1, x=1 Kolejność ++ oraz x sugeruje kolejność czynności: ++x najpierw zwiększa, potem zwraca x, x++ odwrotnie Operatory przyrostkowe i przedrostkowe mają inną hierarchię

Operatory C# • Operatory arytmetyczne (dwuargumentowe): mnożenia: * mnożenie, / dzielenie, % reszta z

Operatory C# • Operatory arytmetyczne (dwuargumentowe): mnożenia: * mnożenie, / dzielenie, % reszta z dzielenia dodawania: + Działają (na ogół) zgodnie z intuicyjnym rozumieniem; Działanie i wynik zależy od typów argumentów: jeżeli oba są całkowite, to działanie jest wykonywane jak dla liczb całkowitych, jeżeli chociaż jeden argument jest zmiennoprzecinkowy, to działanie też: Int 32 i = 3 / 4; // i = 0 Double d = 3. 0 / 4 D; // d = 0. 75 Double z = 3 / 4; // z = 0. 0 Dla typów całkowitych wynik jest przynajmniej Int 32, nawet jeżeli oba argumenty są Byte lub Int 16 Reszta z dzielenia działa też dla liczb zmiennoprzecinkowych (inaczej niż w C/C++) Dla typu String jest zdefiniowany operator +, oznacza konkatenację

Operatory C# • Operatory relacji i równości: relacji: <, <=, >, >= równości: ==

Operatory C# • Operatory relacji i równości: relacji: <, <=, >, >= równości: == != Ich sens jest inny niż w matematyce: nie są stwierdzeniem, lecz pytaniem: Boolean czy. Większe = x > y; Boolean czy. Nierówne = x != y; Rezultat jest true (jeżeli relacja jest prawdziwa) albo false (jeżeli nie)

Operatory C# • Operatory logiczne: negacji (not): ! koniunkcja (and): && alterantywa (or): ||

Operatory C# • Operatory logiczne: negacji (not): ! koniunkcja (and): && alterantywa (or): || Służą do budowania bardziej złożonych wyrażeń logicznych; Należy pamiętać o hierarchii i wiązaniu, a w razie potrzeby stosować nawiasy Boolean warunek = x > y && !(x > 13 || y < 7); Warto zwrócić uwagę na hierarchię – operatory && i || są nisko w hierarchii (za operatorami arytmetycznymi, relacji i równości), więc na ogół nie potrzeba nawiasów, za to "!" jest znacznie wyżej i nawiasy są zwykle potrzebne: W 1 = x > 0 && y > 0; // (x>0) && (y>0) W 2 = x < y + 2 || x == y; // (x<(y+2)) || (x==y) W 3 = !(x < y); // bez () jest błąd, (!x) < y

Operatory C# • Operatory logiczne: negacji (not): ! Operator negacji jest rzadko używany w

Operatory C# • Operatory logiczne: negacji (not): ! Operator negacji jest rzadko używany w wyrażeniach – zawsze można zmienić znak relacji, np. !(x>0) odpowiada x<=0, albo skorzystać z praw De Morgana, np. !(x>0 && y>0) odpowiada x<=0 || y<=0 Operatora negacji używa się w odniesieniu do wartości zwracanych przez funkcje lub właściwości obiektów – ponieważ nie można ani nie warto zmieniać ich działania, np. : while (!stream. End. Of. Stream) { x = stream. Read. Line(); // …

Operatory C# • Operatory logiczne: koniunkcja (and): &&, alterantywa (or): || Program na ogół

Operatory C# • Operatory logiczne: koniunkcja (and): &&, alterantywa (or): || Program na ogół optymalizuje obliczanie koniunkcji i alternatywy: jeżeli w wyrażeniu (a && b) czynnik a ma wartość false, to całość będzie false, niezależnie od wartości b – zatem b nie jest wyznaczane Np. poniżej jeżeli Link. Is. Open ma wartość false, to funkcja Read. Data nie zostanie wywołana: Read. OK = Link. Is. Open && Link. Read. Data(out buffer); Czasami ta właściwość jest wykorzystywana dla skrócenia kodu, ponieważ odpowiednio użyta zastępuje instrukcję if-else: if (!Link. Is. Open) Read. OK = false; else Read. OK = Link. Read. Data(out buffer);

Operatory C# • Operatory logiczne: koniunkcja (and): &&, alterantywa (or): || Podobnie jest optymalizowane

Operatory C# • Operatory logiczne: koniunkcja (and): &&, alterantywa (or): || Podobnie jest optymalizowane wyznaczanie operatora || Przykład: if (Link. Is. Open || Link. Reconnect()) { Link. Read. Data(out buffer); } else { Console. Write. Line(" ? ? ? "); } Kiedy funkcja Reconnect zostanie wykonana, a kiedy nie? Jaki komunikat powinien się pojawić w miejsce "? ? ? " ?

Operatory C# • Operatory przypisania: zwykły: = rozszerzone: *=, +=, … Operator przypisania nie

Operatory C# • Operatory przypisania: zwykły: = rozszerzone: *=, +=, … Operator przypisania nie jest deklaratywny, jest poleceniem wykonywanym w określonym momencie Int 32 a = 7, b = 13, w; w = a + b; // w=20 a = 13; // w=20 Rozszerzone operatory przypisania są tylko skróceniem zapisu: w += 1; // dokładnie jak w = w + 1; w *= b; // dokładnie jak w = w * b; Należy pamiętać, że wiązanie jest prawe: x = y = z = 7; // x=7 x += y *= z -= 3; // z=4, y=28, x=35

Operatory C# • Operatory przypisania: Wszystkie operatory przypisania mają skutek (wstawienie wartości do zmiennej)

Operatory C# • Operatory przypisania: Wszystkie operatory przypisania mają skutek (wstawienie wartości do zmiennej) oraz rezultat (wstawiona wartość), np. rezultatem y=3 jest wartość 3 (ważne: wartość, a nie zmienna lub referencja do niej) Dzięki temu poniższy kod jest poprawny: x = y = 3; Z uwagi na wiązanie prawe operatora = jest to równoważne temu: X = (y = 3); zatem do x jest wstawiany rezultat operacji y=3, czyli 3

Operatory C# • Operatory przypisania: Fakt, że operator = posiada rezultat, pozwala robić np.

Operatory C# • Operatory przypisania: Fakt, że operator = posiada rezultat, pozwala robić np. takie konstrukcje: X = 2 * (y = 3); // ok, y=3, x=6 To działa, ale kod jest mało czytelny, co może prowadzić do błędów, dlatego takie użycie operatora = nie jest zalecane. Ważne są tu nawiasy, ponieważ operator "=" jest najniżej w hierarchii, zaś bez nawiasów będzie błąd składniowy: X = 2 * y = 3; // błąd, (2*y) = 3, (2*y) nie jest zmienną Czasami dopuszcza się takie nadużycie, np. w pętli while: while ("+-*". Index. Of( key = Console. Read. Key(true). Key. Char ) < 0); Wplecenie przypisania do wywołania funkcji jest konieczne, ponieważ w warunku pętli można użyć tylko jednego wyrażenia. Przy okazji – rzadki przykład instrukcji pustej, która nie jest błędem

Operatory C# • Operatory binarne: negacja ~ (NOT), koniunkcja & (AND), alternatywa | (OR),

Operatory C# • Operatory binarne: negacja ~ (NOT), koniunkcja & (AND), alternatywa | (OR), ekskluzja ^ (XOR) Operatory te, w odróżnieniu od operatorów logicznych, są wykonywane na zmiennych całkowitych, bit po bicie, za wyjątkiem bitu znaku, który jest pomijany (o ile występuje). Np. dla koniunkcji (AND), bit wyniku jest równy 1 jeżeli bity obu argumentów na tej samej pozycji są równe 1 Int 32 a = 5, b = 3, c; c = a & b; a: 00000101 b: 00000011 c: 00000001

Operatory C# • Operatory binarne: przesuwania bitów << oraz >> Przesunięcie jest wykonywane nierekursywnie

Operatory C# • Operatory binarne: przesuwania bitów << oraz >> Przesunięcie jest wykonywane nierekursywnie (bity wychodzące poza zmienną NIE są wstawiane na drugim jej końcu), o liczbę pozycji wskazaną drugim argumentem, ale z wyłączeniem bitu znaku: Int 32 a = -15, b; b = a >> 3; a: 100000000 b = a << 10; a: 10000000 b: 100000000 00001111 00000001 // trzy "1" wcięło 00001111 00111100 0000 Przesunięcie w lewo o 1 bit odpowiada mnożeniu przez 2, zaś przesunięcie w prawo – dzieleniu przez 2

Operatory C# • Operator warunkowy ? : W pewnym sensie specyficzna postać instrukcji warunkowej

Operatory C# • Operator warunkowy ? : W pewnym sensie specyficzna postać instrukcji warunkowej (if), króra może być użyta w wyrażeniach; jest też nazywany "inline if": warunek ? wyrażenie 1 : wyrażenie 2 Działanie: obliczana jest wartość warunku, następnie jeżeli warunek jest spełniony, to jako rezultat całego wyrażenia obliczana jest wartość wyrażenia 1, w przeciwnym wypadku wartość wyrażenia 2 Rozsądnie używany upraszcza i skraca zapis kodu, np. : if (x == 0) y = 1. 0; else y = Math. Sin(x) / x; można skrócić do: y = x == 0? 1. 0 : Math. Sin(x) / x;

Operatory C# • Operator warunkowy ? : Ograniczenia – Warunek musi dawać rezultat typu

Operatory C# • Operator warunkowy ? : Ograniczenia – Warunek musi dawać rezultat typu logicznego (Boolean), oba następne wyrażenie muszą być tego samego typu lub musi istnieć automatyczna konwersja między nimi – Może być użyty tylko jako część przypisania albo argument funkcji: // błędy – operator ? : użyty poza przypisaniem x > 0? Console. Write(">") : Console. Write("<="); x == 0? y = 1. 0 : y = Math. Sin(x) / x; // poprawne użycie operatora ? : Console. Write(x>0? ">" : "<="); // ? : jako argument y = x == 0? 1. 0 : Math. Sin(x) / x; // ? : w przypisaniu

Aplikacje konsolowe C# Aplikacje konsolowe • Środowisko VS umożliwia tworzenie aplikacji konsolowych - uruchamianych

Aplikacje konsolowe C# Aplikacje konsolowe • Środowisko VS umożliwia tworzenie aplikacji konsolowych - uruchamianych w klasycznym, czarnym oknie konsoli • Kreator VS tworzy projekt zawierający: - włączenie typowych bibliotek - przestrzeń nazw (można w niej umieszczać własne klasy) - klasę Program - statyczną metodę Main

Aplikacje konsolowe C# Funkcja główna programu • Każdy program musi zawierać funkcję główną (jak

Aplikacje konsolowe C# Funkcja główna programu • Każdy program musi zawierać funkcję główną (jak w C++); wykonanie programu polega na wykonaniu funkcji głównej.

Aplikacje konsolowe C# Przydatne klasy C# • Math - klasa definiująca statyczne metody matematyczne,

Aplikacje konsolowe C# Przydatne klasy C# • Math - klasa definiująca statyczne metody matematyczne, jak pierwiastek, potęga, logarytm, sinus itd. itp Double Sqrt (Double x); Double Pow (Double b, Double e); - oraz dwie stałe: liczby Π oraz e public const Double PI = 3. 14159265358979; public const Double e = 2. 71828459045;

Aplikacje konsolowe C# Przydatne klasy C# • Convert Klasa definiująca konwersje miedzy różnymi typami

Aplikacje konsolowe C# Przydatne klasy C# • Convert Klasa definiująca konwersje miedzy różnymi typami prostymi: Int 16 i 16; Int 32 i 32 = 13; i 16 = Convert. To. Int 16(i 32); // zamiast i 16 = (Int 16)i 32 oraz konwersje z i na typ String ln; Int 32 i 32; ln = Console. Read. Line(); i 32 = Convert. To. Int 32(ln); // zamiast Int 32. Parse(ln); albo krócej Int 32 i 32; i 32 = Convert. To. Int 32(Console. Read. Line());

Aplikacje konsolowe C# Przydatne klasy C# • Console - klasa definiująca szereg statycznych metod

Aplikacje konsolowe C# Przydatne klasy C# • Console - klasa definiująca szereg statycznych metod do obsługi konsoli (odpowiednik strumieni cin oraz cout w C++) - najważniejsze metody: void Write. Line (String line); String Read. Line (); Console. Key. Info Read. Key (Boolean no. Echo);

Aplikacje konsolowe C# Metody klasy Console • Write. Line – wyświetla tekst i przechodzi

Aplikacje konsolowe C# Metody klasy Console • Write. Line – wyświetla tekst i przechodzi do nowej linii - wyświetlenie łańcucha znaków Console. Write. Line("Hello"); - wyświetlenie wartości zmiennej Console. Write. Line(x. To. String()); Console. Write. Line(x); - wyświetlenie kilku informacji Console. Write. Line("Wynik = " + x); Console. Write. Line("Suma {0} i {1} to {2}", a, b, s);

Aplikacje konsolowe C# Metody klasy Console • Read. Line – wczytuje tekst wpisany z

Aplikacje konsolowe C# Metody klasy Console • Read. Line – wczytuje tekst wpisany z klawiatury (do naciśnięcia <Enter>) - wczytanie łańcucha znaków i konwersja na liczbę String ln; Double x; ln = Console. Read. Line (); x = Double. Parse(ln); - jw. , ale z wykrywaniem błędów Boolean ok; ok = Double. Try. Parse(ln, out x);

Aplikacje konsolowe C# Przykład aplikacji konsolowej C#

Aplikacje konsolowe C# Przykład aplikacji konsolowej C#

Instrukcje C# • • • Instrukcja Instrukcja Instrukcje wyrażeniowa pusta blokowa warunkowa (if oraz

Instrukcje C# • • • Instrukcja Instrukcja Instrukcje wyrażeniowa pusta blokowa warunkowa (if oraz if-else) wyboru (switch) iteracyjne (for, while, do-while, foreach)

Instrukcje C# • Instrukcja wyrażeniowa: wyrażenie; Wyrażenie (kombinacja literałów, zmiennych, wywołań funkcji oraz operatorów)

Instrukcje C# • Instrukcja wyrażeniowa: wyrażenie; Wyrażenie (kombinacja literałów, zmiennych, wywołań funkcji oraz operatorów) zakończone średnikiem, np. : promień++; pole = 2 * Math. PI * Math. Pow(promień, 2. 0); Console. Write. Line("Pole wynosi {0}", pole); Nie każde wyrażenie może stać się instrukcją – jedynie przypisanie, inkrementacja, dekrementacja, wywołanie funkcji oraz operator new

Instrukcje C# • Instrukcja pusta: ; Stosuje się tam, gdzie składnia języka wymaga podania

Instrukcje C# • Instrukcja pusta: ; Stosuje się tam, gdzie składnia języka wymaga podania instrukcji, a nic konkretnego nie ma być zrobione. Instrukcja pusta przydaje się bardzo rzadko, a jej użycie w instrukcjach warunkowych i iteracyjnych najczęściej jest błędem, np. : if (delta<0); Console. Write. Line("Brak pierwiastków"); Średnik po warunku tworzy instrukcję pustą (która jest lub nie jest wykonywana, zależnie od wyniku sprawdzenia warunku), natomiast wydruk jest wykonywany zawsze, ponieważ w tej sytuacji NIE JEST częścią instrukcji warunkowej.

Instrukcje C# • Instrukcja blokowa { //dowolna liczba instrukcji } Stosuje się wtedy, gdy

Instrukcje C# • Instrukcja blokowa { //dowolna liczba instrukcji } Stosuje się wtedy, gdy składnia pozwala na użycie tylko jednej instrukcji, a trzeba użyć większej ich liczby. Przykład: for (i=1; i<=10; i++) { k = i*i; Console. Write. Line("kwadrat {0} to {1}", i, k); } Intencją programisty jest, aby każda iteracja składała się z dwóch instrukcji (obliczenia i wydruk). Składnia for pozwala na użycie tylko jednej instrukcji, zatem konieczne jest użycie instrukcji grupującej.

Instrukcje C# • Instrukcja warunkowa if if (warunek) instrukcja Program oblicza wartość wyrażenia podanego

Instrukcje C# • Instrukcja warunkowa if if (warunek) instrukcja Program oblicza wartość wyrażenia podanego jako "warunek" (musi to być wyrażenie dające rezultat typu Boolean). Jeżeli warunek jest spełniony (wartość logiczna true), program wykonuje instrukcję, w przeciwnym wypadku instrukcja jest pomijana if (a != b) Console. Write. Line("a i b są rózne”);

Instrukcje C# • Instrukcja warunkowa if -else if (warunek) instrukcja_1 else instrukcja_2 Program oblicza

Instrukcje C# • Instrukcja warunkowa if -else if (warunek) instrukcja_1 else instrukcja_2 Program oblicza wartość wyrażenia podanego jako "warunek" (musi to być wyrażenie dające rezultat typu Boolean). Jeżeli warunek jest spełniony (wartość logiczna true), wykonywana jest tylko instrukcja_1, w przeciwnym wypadku wykonywana jest tylko instrukcja_2 if (x != 0) y = sin(x)/x; else y = 1;

Instrukcje C# • Instrukcja wyboru switch-case Można ją traktować jako uogólnienie instrukcji warunkowej if-else

Instrukcje C# • Instrukcja wyboru switch-case Można ją traktować jako uogólnienie instrukcji warunkowej if-else O ile instrukcja warunkowa daje dwa warianty działania (dla dwóch możliwych wartości logicznych), to kluczem instrukcji wyboru może być dowolny typ prosty całkowity, znakowy, łańcuch znaków albo typ wyliczeniowy, więc możliwych jest wiele opcji W przeciwieństwie do C/C++, kluczem instrukcji wyboru może być także łańcuch znaków

Instrukcje C# • Instrukcja wyboru switch-case switch (klucz) { case etykieta 1: instrukcje break;

Instrukcje C# • Instrukcja wyboru switch-case switch (klucz) { case etykieta 1: instrukcje break; case etykieta 2: instrukcje break; default: instrukcje break; } Klucz – wyrażenie dające rezultat typu całkowitego, znakowego, łańcuch znaków albo typu wyliczeniowego Etykieta – literał typu zgodnego z typem klucza

Instrukcje C# • Instrukcja wyboru switch-case Zasady i ograniczenia: – Typy etykiet muszą być

Instrukcje C# • Instrukcja wyboru switch-case Zasady i ograniczenia: – Typy etykiet muszą być zgodne z typem klucza – Etykiety muszą być wartościami (literałami lub stałymi), Wartości etykiet nie mogą się powtarzać; – Sekcja "default" jest opcjonalna, może wystąpić co najwyżej raz – Każda sekcja case MUSI być zakończona instrukcją break – Kilka etykiet może mieć wspólny blok kodu switch (n) { case 1: case 7: // kod wspólny dla 1 i 7 break; // itd. .

Instrukcje C# • Instrukcja wyboru switch-case command = Console. Read. Line(); switch (command) {

Instrukcje C# • Instrukcja wyboru switch-case command = Console. Read. Line(); switch (command) { case "login": User. Login(); break; case "exit": case "bye": Disconnect(); break; default: Console. Write. Line("Unknown command"); break; }

Instrukcje C# • Instrukcja iteracyjna for Instrukcja iteracyjna z licznikiem, dobrze znana już ze

Instrukcje C# • Instrukcja iteracyjna for Instrukcja iteracyjna z licznikiem, dobrze znana już ze starszych języków programowania – powinna być stosowana przede wszystkim tam, gdzie Z GÓRY wiadomo ile dokładnie razy należy powtórzyć czynność – np. obliczenie silni z 7, wydrukowanie tablicy 100 liczb itp. W językach C/C++ instrukcja for zyskała dużą elastyczność, np. licznik pętli nie musi być całkowity (w językach Basic i Pascal musi)

Instrukcje C# • Instrukcja iteracyjna for (inicjalizacja; warunek; inkrementacja) instrukcja Program wykonuje wyrażenie inicjalizacji,

Instrukcje C# • Instrukcja iteracyjna for (inicjalizacja; warunek; inkrementacja) instrukcja Program wykonuje wyrażenie inicjalizacji, następnie oblicza wartość wyrażenia podanego jako "warunek" (musi to być wyrażenie dające rezultat typu Boolean). Jeżeli warunek jest spełniony (wartość logiczna true), program wykonuje instrukcję oraz inkrementację, po czym czynności SĄ POWTARZANE, począwszy od wyznaczenia warunku; Jeżeli warunek nie jest spełniony, to następuje wyjście z pętli. We wszystkich instrukcjach iteracyjnych (for, while, do-while) "warunek" jest warunkiem pozostania w pętli, a nie wyjścia z niej.

Instrukcje C# • Instrukcja iteracyjna for (inicjalizacja; warunek; inkrementacja) instrukcja inicjalizacja false warunek true

Instrukcje C# • Instrukcja iteracyjna for (inicjalizacja; warunek; inkrementacja) instrukcja inicjalizacja false warunek true instrukcja inkrementacja

Instrukcje C# • Instrukcja iteracyjna for, przykłady // klasyczna iteracja for (i = 1;

Instrukcje C# • Instrukcja iteracyjna for, przykłady // klasyczna iteracja for (i = 1; i <= 10; i++) Console. Write. Line(i); //liczenie wstecz – zmienia się też warunek (na ">")! for (i = 77; i > 0; i -= 7) Console. Write. Line(i); // licznik niecałkowity for (Double d = 0. 2; d <= 2. 8; d += 0. 15) Console. Write. Line(d); // formalnie poprawna, zawiesza program for (; ; ) ;

Instrukcje C# • Instrukcja iteracyjna while Instrukcja iteracyjna z warunkiem – powinna być stosowana

Instrukcje C# • Instrukcja iteracyjna while Instrukcja iteracyjna z warunkiem – powinna być stosowana przede wszystkim tam, gdzie nie wiadomo ile dokładnie razy należy powtórzyć czynność, natomiast sprawdzenie, czynność ma być powtarzana, powinna być zrobiona za każdym razem PRZED tą czynnością. Klasycznym przykładem while jest odczyt pliku tekstowego: nie wiadomo ile linii zawiera plik (więc nie for), ale przed próbą odczytu można sprawdzić, czy program osiągnął koniec pliku: while (NIE koniec pliku) { linia = plik. Czytaj. Linię(); // użycie odczytanej linii }

Instrukcje C# • Instrukcja iteracyjna while (warunek) instrukcja Program oblicza wartość wyrażenia podanego jako

Instrukcje C# • Instrukcja iteracyjna while (warunek) instrukcja Program oblicza wartość wyrażenia podanego jako "warunek" (musi to być wyrażenie dające rezultat typu Boolean). Jeżeli warunek jest spełniony (wartość logiczna true), program wykonuje instrukcję, po czym czynności SĄ POWTARZANE; Jeżeli warunek nie jest spełniony, to następuje wyjście z pętli. Jeżeli warunek od początku nie jest spełniony, to instrukcja nie jest wykonana nawet raz

Instrukcje C# • Instrukcja iteracyjna while (warunek) instrukcja false warunek true instrukcja

Instrukcje C# • Instrukcja iteracyjna while (warunek) instrukcja false warunek true instrukcja

Instrukcje C# • Instrukcja iteracyjna while, przykłady // kopiowanie pliku na ekran String line;

Instrukcje C# • Instrukcja iteracyjna while, przykłady // kopiowanie pliku na ekran String line; Stream. Reader plik = new Stream. Reader(@"C: plik. txt"); while (!plik. End. Of. Stream) { line = plik. Read. Line(); Console. Write. Line(line); } // formalnie poprawna, chociaż zawiesza program while (true) ;

Instrukcje C# • Instrukcja iteracyjna do-while Instrukcja iteracyjna z warunkiem – powinna być stosowana

Instrukcje C# • Instrukcja iteracyjna do-while Instrukcja iteracyjna z warunkiem – powinna być stosowana tam, gdzie nie wiadomo ile dokładnie razy należy powtórzyć czynność, natomiast sprawdzenie czynność ma być nadal powtarzana może być zrobiona dopiero PO tej czynności. Klasycznym przykładem do-while są iteracyjne obliczenia, których powtarzanie zwiększa dokładność wyniku, zaś oceny tej dokładności można dokonać dopiero PO wykonaniu obliczeń, np. rozwiązywanie równań nieliniowych metodą Newtona: do { x = Dokładniejsze. Rozwiązanie (x); e = Szacunkowy. Błąd (x); } while (e > Dopuszczalny. Błąd);

Instrukcje C# • Instrukcja iteracyjna while do { instrukcja } while (warunek); Program wykonuje

Instrukcje C# • Instrukcja iteracyjna while do { instrukcja } while (warunek); Program wykonuje instrukcję , a następnie oblicza wartość wyrażenia podanego jako "warunek" (musi to być wyrażenie dające rezultat typu Boolean). Jeżeli warunek jest spełniony (wartość logiczna true), to czynności SĄ POWTARZANE; Jeżeli warunek nie jest spełniony, to następuje wyjście z pętli. Instrukcja zostanie wykonana przynajmniej raz

Instrukcje C# • Instrukcja iteracyjna while do { instrukcja } while (warunek); instrukcja true

Instrukcje C# • Instrukcja iteracyjna while do { instrukcja } while (warunek); instrukcja true warunek false

Instrukcje C# • Instrukcja iteracyjna do-while, przykłady // obliczanie przybliżonej wartości pierwiastka Double x

Instrukcje C# • Instrukcja iteracyjna do-while, przykłady // obliczanie przybliżonej wartości pierwiastka Double x = 4. 0, px = 4. 0, e; do { px = 0. 5 * (px + x / px); e = (px * px - x) / x; } while (e > 0. 001);

Instrukcje C# • Instrukcje break i continue Służą do kontrolowania instrukcji iteracyjnych: - continue

Instrukcje C# • Instrukcje break i continue Służą do kontrolowania instrukcji iteracyjnych: - continue przerywa bieżącą iterację, ale pętla jest dalej wykonywana - break natychmiast kończy pętlę Są używane ZAWSZE w powiązaniu z instrukcją warunkową (inaczej to, co jest za nimi, nigdy nie będzie wykonane) // pominięcie iteracji dla y<0 for (x = 0; x <= 10. 0; x += 0. 01) { y = … // obliczenia if (y < 0) continue; z = … // obliczenia }

Instrukcje C# • Instrukcje break i continue W nietypowych sytuacjach (np. kiedy sytuacja nie

Instrukcje C# • Instrukcje break i continue W nietypowych sytuacjach (np. kiedy sytuacja nie pozwala na użycie pętli while lub do-while), stosuję się pętlę "nieskończoną", z której wyjście jest możliwe tylko przez instrukcję break. while (true) { // instrukcje if (warunek) break; // instrukcje }

Instrukcje C# • Instrukcje break i continue Klasyczny przykład pętli "nieskończonej" z break –

Instrukcje C# • Instrukcje break i continue Klasyczny przykład pętli "nieskończonej" z break – NWD Euklidesa dzielna = …; dzielnik = …; while (true) { reszta = dzielna % dzielnik if (reszta == 0) break; dzielna = dzielnik; dzielnik = reszta; } NWD = dzielnik;

Instrukcje C# • Przykład łączący różne instrukcje – aplikacja konsolowa realizujące wielokrotnie działania, zależnie

Instrukcje C# • Przykład łączący różne instrukcje – aplikacja konsolowa realizujące wielokrotnie działania, zależnie od wyboru użytkownika; Char key; Console. Write. Line("Naciśnij + (? ? ? ), - (? ? ? ) albo * (koniec)"); while (true) { while ("+-*". Index. Of(key = Console. Read. Key(true). Key. Char) < 0); if (key == '*') break; switch (key) { case '+': Console. Write. Line("Działania dla +"); break; case '-': Console. Write. Line("Działania dla -"); break; } }

Wyjątki programowe Wyjątek programowy to rodzaj sytuacji nadzwyczajnej, np. błędu, z którym program nie

Wyjątki programowe Wyjątek programowy to rodzaj sytuacji nadzwyczajnej, np. błędu, z którym program nie potrafi sobie poradzić, którego obsłużenie jest oddane "wyższym warstwom" programu • Przykład: jeżeli funkcja Int 32. Parse otrzyma do przetworzenia ciąg znaków, który nie jest liczbą całkowitą, to wygeneruje wyjątek; Funkcja Parse nie może naprawić błędu, nie powinna też decydować jak zareagować na błąd (to należy do "wyższej warstwy" programu) • Jeżeli wyjątek nie zostanie obsłużony, to program zostanie zatrzymany Do obsługi wyjątków służą instrukcje: • throw – rzucanie wyjątku • try-catch – obsługa wyjątku • try-finally – czyszczenie po wystąpieniu wyjątku

Tablice C# Tablica to indeksowany zbiór elementów • Tablica jest typem referencyjnym (deklaracja tworzy

Tablice C# Tablica to indeksowany zbiór elementów • Tablica jest typem referencyjnym (deklaracja tworzy tylko referencję, sama tablica musi być utworzona oddzielnie, najprościej operatorem new) • Wszystkie elementy tablicy są tego samego typu • Dostęp do elementów tablicy daje operator indeksowania [] (Ważne: indeks zaczyna się zawsze od wartości 0, a nie 1) • Tablice mogą być jedno- lub wielowymiarowe • Można tworzyć tablice tablic (jest to coś innego, niż tablica wielowymiarowa)

Tablice C# • Deklaracja tablicy Można zadeklarować tablicę elementów dowolnego typu (wartościowego lub referencyjnego),

Tablice C# • Deklaracja tablicy Można zadeklarować tablicę elementów dowolnego typu (wartościowego lub referencyjnego), dopisując "[]" po typie: Int 32[] t 1; Button[] t 2; // tablica liczb Int 32 // tablica referencji przycisków Użycie "[]" po nazwie typu deklaruje tablicę jednowymiarową, użycie "[ , ]" dwuwymiarową, "[ , , ]" trzywymiarową itd. Int 32[ , ] t 3; // tablica dwuwymiarowa

Tablice C# • Deklaracja tablicy Można połączyć deklarację tablicy z jej utworzeniem i nadaniem

Tablice C# • Deklaracja tablicy Można połączyć deklarację tablicy z jej utworzeniem i nadaniem wartości – wówczas rozmiar tablicy wynika z inicjalizatora. Inicjalizator tablicy to lista elementów, zapisana w nawiasach klamrowych i oddzielonych przecinkami: { p 0, p 1, p 2, … pk-1 } Jeżeli tablica jest wielowymiarowa, to konstrukcja ta musi zostać zagnieżdżona, np. w tablicy trójwymiarowej każde p jest tablicą elementów q, a każde q jest tablicą elementów r: { p 0, p 1, p 2, … pk-1 } {{q 0, …ql-1}, … {q 0, …ql-1}} {{{r 0, …rm-1}, …{r 0, …rm-1}}, … {{r 0, …rm-1}, …{r 0, …rm-1}}}

Tablice C# • Deklaracja tablicy Przykłady: // tablica jednowymiarowa 4 el. Int 32[] t

Tablice C# • Deklaracja tablicy Przykłady: // tablica jednowymiarowa 4 el. Int 32[] t 1 = { 1, 2, 3, 4 }; // tablica dwuwymiarowa 2 x 3 el. Int 32[, ] t 2 = { { 1, 2, 3 }, { 4, 5, 6 } }; // tablica Int 32[, , ] { { {1, 2, { {3, 4, trójwymiarowa 2 x 3 x 4 el. t 3 = 3, 4}, {5, 6, 7, 8}, {9, 0, 1, 2} } 5, 6}, {7, 8, 9, 0}, {1, 2, 3, 4} } };

Tablice C# • Utworzenie tablicy W celu utworzenia tablicy należy użyć operatora new, podając

Tablice C# • Utworzenie tablicy W celu utworzenia tablicy należy użyć operatora new, podając rozmiar tablicy: Int 32[] t 1; t 1 = new Int 32[5]; // deklaracja tablicy // utworzenie tablicy Deklarację i utworzenie tablicy można połączyć: Double[] t 2 = new Double[3]; Int 32[, ] t 3 = new Int 32[3, 5]; Można też połączyć utworzenie tablicy z nadaniem wartości; Liczba elementów musi być równa rozmiarowi Int 32[] t 4 = new Int 32[3] {1, 2, 3}; Int 32[] t 5 = new Int 32[3] {1, 2}; // ok // błąd!

Tablice C# • Utworzenie tablicy Rozmiar tablicy może być stałą całkowitą, ale też zmienną

Tablice C# • Utworzenie tablicy Rozmiar tablicy może być stałą całkowitą, ale też zmienną lub dowolnym wyrażeniem o rezultacie całkowitym: Int 32[] t 1, t 2, t 3; Int 32 r = 7; t 1 = new Int 32[7]; t 2 = new Int 32[r]; t 3 = new Int 32[2 * r + 1]; To ważne – rozmiar nie musi być znany w czasie kompilacji, można utworzyć tablicę o rozmiarze zależnym od wykonania programu, np. podanym przez użytkownika

Tablice C# • Wartości domyślne elementów Podczas tworzenia tablicy, jej wszystkie elementy są inicjalizowane

Tablice C# • Wartości domyślne elementów Podczas tworzenia tablicy, jej wszystkie elementy są inicjalizowane tzw. wartością domyślną: – – – 0 lub 0. 0 dla typów prostych liczbowych, false dla typu Boolean '' dla znaków, "" (łańcuch pusty) dla łańcuchów null dla typów referencyjnych To inaczej, niż w C/C++, gdzie tablice nie są inicjalizowane, a po utworzeniu zawierają wartości przypadkowe (tj. śmieci pozostałe po poprzednio używanych zmiennych) To również inaczej, niż zwykłe zmienne w C#, które także nie są inicjowane

Tablice C# Wartości null • Dotyczy wyłącznie typów referencyjnych i oznacza referencję pustą, tj.

Tablice C# Wartości null • Dotyczy wyłącznie typów referencyjnych i oznacza referencję pustą, tj. że obiekt wskazywany przez referencję nie istnieje. • Wartość null ma istotne znaczenie praktyczne, np. pozwala sprawdzić, czy obiekt istnieje: obiect o = Try. Create. Obiect(); if (o != null) // = jeżeli obiekt istnieje • Przypisanie null do zmiennej referencyjnej jest dla CLR sygnałem, że obiekt wskazywany przez nią nie jest potrzebny, więc jego zasoby mogą zostać zwolnione przez GC: object o = new object(); // … o = null; // zwolnienie zasobów obiektu przez GC

Tablice C# • Indeksowanie Dostęp do elementów tablicy daje operator indeksowania []. Numery indeksów

Tablice C# • Indeksowanie Dostęp do elementów tablicy daje operator indeksowania []. Numery indeksów zaczynają się od 0, zatem tablica o rozmiarze N ma indeksy od 0 do N-1 Int 32[] t = new Int 32[3]; Int 32 suma; t[0] = 7; // pierwszy element t[1] = 13; // drugi t[2] = 77; // trzeci i ostatni suma = t[0] + t[1] + t[2]; Próba odczytu lub przypisania elementu o indeksie spoza zakresu 0…N-1 spowoduje wyjątek programowy t[3] = 0; // błąd!

Tablice C# • Indeksowanie Indeks może być stałą całkowitą, ale też zmienną lub dowolnym

Tablice C# • Indeksowanie Indeks może być stałą całkowitą, ale też zmienną lub dowolnym wyrażeniem o rezultacie całkowitym: Int 32[] t = new Int 32[100]; Int 32 i = 7; t[i] = 7; t[i+1] = 13; t[7*i + 13] = 77; t[2*t[i] + 3] = 169; To ważne – umożliwia przetwarzanie tablic przy pomocy pętli, oczywiście najczęściej jest to pętla for

Tablice C# • Indeksowanie Do przetwarzania tablic prawie zawsze najlepszym wyborem jest pętla for

Tablice C# • Indeksowanie Do przetwarzania tablic prawie zawsze najlepszym wyborem jest pętla for – ponieważ liczba elementów jest znana: Random r = new Random(); Int 32 i; Int 32[] t = new Int 32[100]; for (i = 0; i < 100; i++) t[i] = r. Next(); Dla liczb całkowitych równoważnie można napisać Int 32[] t = new Int 32[100]; for (i = 0; i <= 99; i++) jednak taki zapis zwiększa ryzyko błędu

Tablice C# • Indeksowanie Sposób konstrukcji pętli z warunkiem "licznik < rozmiar" jest jeszcze

Tablice C# • Indeksowanie Sposób konstrukcji pętli z warunkiem "licznik < rozmiar" jest jeszcze bardziej czytelny, gdy rozmiar jest zmienną: Random r = new Random(); Int 32 i, N = 100; Int 32[] t = new Int 32[N]; for (i = 0; i < N; i++) t[i] = r. Next(); Tym bardziej, że np. w algorytmach sortowania przegląda się tablicę od pierwszego do przedostatniego elementu, co w takim zapisie jest wyraźnie widoczne: for (i = 0; i < N - 1; i++) Równoważny zapis i <= N– 2 sugeruje coś innego!

Tablice C# • Tablice tablic Tablica może zawierać elementy dowolnego typu, zatem również inne

Tablice C# • Tablice tablic Tablica może zawierać elementy dowolnego typu, zatem również inne tablice. Tablice tablic NIE są tablicami dwuwymiarowymi (nie można stosować ich zamiennie): Int 32[, ] t 2 w; Int 32[][] tt; // tablica dwuwymiarowa // tablica tablic Tablice tablic wymagają dwuetapowego tworzenia: tt = new Int 32[][2]; tt[0] = new Int 32[5]; tt[1] = new Int 32[10]; Tablice wchodzące w skład tablicy tablic mogą mieć różne rozmiary, dlatego takie tablice są nazywane jigged tables (tablice szczerbate)

Tablice C# Klasa Array • Klasa Array jest tzw. klasą uniwersalną – reprezentuje tablicę

Tablice C# Klasa Array • Klasa Array jest tzw. klasą uniwersalną – reprezentuje tablicę elementów dowolnego typu • Jest to klasa abstrakcyjna – nie można utworzyć obiektu Array • Każda tablica, niezależnie od typu elementów składowych, należy do klasy Array (do zmiennej typu Array można przypisać dowolną tablicę), odwrotne przypisanie wymaga rzutowania Int 32[] t = new Int 32[3]; Array a; a a t t = = new Array(); t; a; (Int 32[])a; // // błąd! ok

Tablice C# Klasa Array • Klasa Array udostępnia wiele przydatnych właściwości i metod; •

Tablice C# Klasa Array • Klasa Array udostępnia wiele przydatnych właściwości i metod; • Większość z nich to metody statyczne (wywoływane przez klasę Array, a nie obiekt tej klasy; pierwszym argumentem metody jest tablica) Int 32[] t 1 = { 1, 2, 3, 4 }; Int 32[] t 2; Int 32 i; i = Array. Index. Of(t 1, 3); // Array. Reverse(t 1); // t 2 = Array. Find. All(t 1, n => n%2==0); // Array. Sort(t 2); // 2 {4, 3, 2, 1} {4, 2} {2, 4}

Tablice C# Klasa Array • Klasa Array – metody statyczne – – – –

Tablice C# Klasa Array • Klasa Array – metody statyczne – – – – Create. Instance – tworzy tablicę obiektów wskazanego typu Copy – kopiuje fragment tablicy do innej tablicy Find, Find. All – znajduje elementy spełniające określony warunek Find. Index – znajduje element spełniający warunek i zwraca jego indeks Index. Of – znajduje element o określonej wartości i zwraca jego indeks Resize – zmienia rozmiar tablicy Reverse – odwraca kolejność elementów Sort – sortuje tablicę (jest kilkanaście wersji tej metody, można m. in. podać niestandardowy komparator)

Tablice C# Klasa Array • Klasa Array – właściwości i metody instancji (tj. dostępne

Tablice C# Klasa Array • Klasa Array – właściwości i metody instancji (tj. dostępne przez zmienne klasy Array) metody: – Clone – tworzy tzw. płytką kopię tablicy – Copy. To – kopiuje fragment tablicy do innej tablicy – Get. Length – podaje liczbę elementów określonego wymiaru właściwości – Rank – liczba wymiarów (liczona od zera!) – Length – łączna (dla wszystkich wymiarów) liczba elementów for (i=0; i<t. Length; i++) Console. Write. Line(t[i]);

Tablice C# Klasa Enumerable • Klasa statyczna, dostarcza kilkadziesiąt (!) statycznych metod przetwarzania dowolnych

Tablice C# Klasa Enumerable • Klasa statyczna, dostarcza kilkadziesiąt (!) statycznych metod przetwarzania dowolnych obiektów implementujących interfejs IEnumerable, tj. różne kolekcje (klasa Array też) • Wszystkie metody są zdefiniowane jako tzw. rozszerzenia (extension), mogą być wywoływane na 2 sposoby: – przez klasę Enumerable – przez obiekt dowolnej klasy implementującej IEnumerable (znacznie wygodniej, można wykonać kilka operacji) Int 32[] t 1 = { 1, 2, 3, 4 }; Double avg; avg = Enumarable. Average(t 1); avg = t 1. Average();

Tablice C# Klasa Enumerable • Wiele metod daje jako rezultat kolekcję, jednak aby zapisać

Tablice C# Klasa Enumerable • Wiele metod daje jako rezultat kolekcję, jednak aby zapisać go jako tablicę, należy użyć metody To. Array Int 32[] t 1 = { 1, 2, 3, 4 }; Int 32[] t 2; t 2 = t 1. Reverse(). To. Array(); // {4, 3, 2, 1} • Wywołania wielu kolejnych metod Enumerable można połączyć w łańcuch – kolejna metoda łańcucha przetwarza rezultat dostarczony przez metodę poprzednią Int 32[] t 3 = { 2, 1, 2, 3, 2, 4 }; Int 32[] t 4; t 4 = t 3. Distinct(). Where(n => n<4). Reverse(). To. Array; // {3, 1, 2}

Tablice C# Klasa Enumerable, wybrane metody: – – – – All – sprawdza czy

Tablice C# Klasa Enumerable, wybrane metody: – – – – All – sprawdza czy wszystkie elementy spełniają wskazane kryterium Any – sprawdza czy choć jeden elementy spełnia wskazane kryterium Average – oblicza wartość średnią (elementy muszą być liczbami) Concat – łączy dwie kolekcje Contains – sprawdza czy kolekcja zawiera wskazany element Distinct – zwraca kolekcję elementów unikalnych (bez powtórzeń) Except – zwraca kolekcję za wyjątkiem wskazanych (różnica zbiorów) Max – zwraca wartość maksymalną (elementy muszą być liczbami) Min – zwraca wartość minimalną Order. By – sortuje według wybranego klucza i opcjonalnie komparatora Select – zwraca kolekcję elementów przetworzonych p. zał. funkcję Sum – oblicza sumę (elementy muszą być liczbami) Where – zwraca podzbiór elementów spełniających zał. kryterium To. List – przekształca kolekcję w listę To. Array – przekształca kolekcję w tablicę