C# przykłady kodu. Spis treści: - pierwszy program - typy danych - zmienne - wyliczenia - operatory - Instrukcje sterujące - Programowanie obiektowe - Klasa - Metody - Konstruktor - Dziedziczenie i przeciążanie metod - Obiekt (tworzenie) - interfejsy - Tablice - Tablica - obiekt - Używanie tablic - Tablica wielowymiarowa: - Tablice nieregularne - Wyjątki - opis - przykład - Wyrzucanie wyjątków - Interfejsy - GUI (simple) - Delegaty i zdarzenia Opis jest np. http://pl.wikibooks.org/wiki/C_sharp ------------------------------------------- pierwszy program using System; // kompilator będzie używać przestrzeni nazw System public class Klasa { public static void Main (string[] args) { Console.WriteLine("Witaj świecie!"); } } Zapisujemy to wszystko jako np. program.cs i kompilujemy. Uruchamiamy program poleceniem: program.exe Uwaga! Dla użytkownika jest to plik identyczny, jak każdy inny plik wykonalny. Dla nas - programistów - zwykły plik wykonywalny, a plik napisany w C# różni wnętrze. W 'środku' tego pliku jest pakiet napisany we Wspólnym Języku Pośrednim - CIL/MSIL - przykład drugi using System; public class PrzykladowaKlasa { public static void Main() { Console.WriteLine("Podaj swoje imie:"); string imie = Console.ReadLine(); Console.WriteLine("Twoje imie to: " + imie); Console.WriteLine("Wcisnij dowolny klawisz by zakonczyc program."); Console.ReadKey(); } } - kostka do gry A to trochę inny program symulujący uniwersalną kostkę do gry, można w nim zobaczyć kilka podstawowych instrukcji języka C#. using System; public class Kostka { public static void Main() { int kostka=0; Random liczba = new Random(); string str=""; Console.Clear(); while (true) { Console.Write("Iluscienna kostka chcesz grac?: "); try { kostka = int.Parse(Console.ReadLine()); } catch { Console.WriteLine("Podano nieprawidlowe dane!"); kostka = 0; } if (kostka<4) {Console.WriteLine("Kostka ma minimum 4 ściany.");} else break; } Console.Clear(); while (str != "q") { Console.WriteLine("Wylosowana liczba to :" + (liczba.Next(kostka) + 1).ToString() + "\tAby zakonczyc wcisnij q + enter"); str = Console.ReadLine(); } } } ------------------------------------------------------ Typy danych Typy danych dzielimy na dwie podstawowe grupy: * Typy Wartościowe - prosty - wyliczenie - struktura * Typy Referencyjne - klasa - interfejs - delegacja - tablica Typy proste: bool true lub false byte 0 do 255 short -2^15 do 2^15-1 int -2^31 do 2^31-1 long -2^63 do 2^63-1 float +-1,5*10^(-45) do 3,4*10^38 double +-5,0*10^(-324) do 1,7*10^308 char Pojedynczy znak Unicode string Ciąg znaków Unicode - Zmienne: int zmienna; zmienna = 10; lub int zmienna = 10; Ponownie istnieją dwie metody użycia zmiennej: string zmienna = "Lalala"; Console.Writeline("Moja zmienna to:"+zmienna); lub string zmienna = "Lalala"; Console.Writeline("Moja zmienna to:{0}", zmienna); - Wyliczenia enum PoryRoku { Wiosna, Lato, Jesien, Zima } lub enum PoryRoku { Wiosna = 0; Lato = 1; Jesien = 2; Zima = 3; } albo: enum PoryRoku { Wiosna = 1; //nowa wartość dla wiosny, oznacza nowe wartości dla reszty pór roku. Lato, //Lato = 2 Jesien, //Jesien = 3 Zima, //Zima = 4 } ------------------------------------------- Operatory: - Operatory arytmetyczne + dodawanie - odejmowanie * mnożenie / dzielenie % dzielenie modulo (reszta z dzielenia) ++ inkrementacja -- dekrementacja W tych dwóch ostatnich występuje podział na post- i pre-. Pre- ink/dekrementuje przed użyciem a post- po użyciu zmiennej. - Operatory bitowe bitowe AND & bitowe OR | XOR ^ przesunięcia bitowe lewe i prawe << >> - Operatory logiczne logiczne AND (i) && logiczne OR (lub) || negację logiczną NOT (nie) ! - Operatory przypisania Służą do przypisywania wartości zmiennej. Oprócz prostego = mamy także jego połączenia z innymi operatorami np. +=, <<= czy &= = Operatory porównania Służą do porównywania wartości po obu swoich stronach. Mamy ==,!=,<,>,<=,>= -------------------------- Instrukcje sterujące - Instrukcja if if(warunek) //instrukcja do wykonania, jeśli więcej to w klamerce if(warunek){ //instrukcje } else{ //instrukcje jeśli niespełniony warunek } if(warunek1){ //instrukcje } else if(warunek2){ //instrukcje jeśli niespełniony warunek1, ale spełniony warunek2 } else{ //instrukcje jeśli niespełniony warunek1 ani warunek2 } - Instrukcja switch switch(a){ case 1: //instrukcje1; break; //konieczne case 2: //instrukcje2; break; default: //jeśli żaden niespełniony //instrukcje; break; } - pętla for for (int i=1;i<=100;i++){ Console.WriteLine(i.ToString()); } (Z każdym kolejnym przejściem pętli zmienna i jest postinkremetowana) - Instrukcja foreach Pętla ta rożni się nieco od for. Przechodzi kolejno przez wszystkie elementy tablicy lub innej kolekcji. Przechodząc przez dany element zapisuje go do zmiennej tymczasowej zdefiniowanej w nagłówku pętli. Taka zmienna tworzona jest dokładnie raz dla każdego elementu. Zmienna ta jest dostępna tylko do odczytu a każda próba ustawienia jej wartości wywoła błąd podczas kompilacji. Dla tablic jednowymiarowych przejście następuje od indeksu 0 i postępuje w porządku rosnącym. W przypadku tablic wielowymiarowych przeszukanie następuje dla skrajnie prawego indeksu. int[] tab = {1, 2, 3, 4, 5}; foreach(int val in tab) { Console.WriteLine(val.ToString()); } - Instrukcja while while (wyrażenie logiczne) { ciało pętli } Instrukcje zawarte w ciele pętli wykonywane są dopóki wyrażenie logiczne jest prawdziwe. Jeżeli wyrażenie od początku będzie miało wartość false ciało nie wykona się. int a=1; while (a<=100){ Console.WriteLine(a.ToString()); a++; } ------------------------------------------- Programowanie obiektowe - klasa [atrybuty] [modyfikatory dostępu] class nazwaNowejKlasy [klasa bazowa] [, interfejsy]] using System; class Klasa { public const int x = 5; public const string y = "string"; } class Program { static void Main() { //Prawidłowe odwołanie się do stałej Console.WriteLine(Klasa.y); Klasa c = new Klasa(); //Poniższa instrukcja spowoduje błąd //Dostęp do stałej za pośrednictwem obiektu jest niemożliwy Console.WriteLine(c.y); } } - Właściwości (Umożliwiają kontrolowany dostęp do wartości zapisanych wewnątrz klasy) Składnia : [atrybut] { [modyfikator] get { ...... return(wartość właściwości) } [modyfikator]set { //kod zapisujący do pola wartość reprezentowaną przez zmienną value } } Blok get wykonywane jest podczas żądania wartości właściwości. Natomiast blok set podczas próby zapisania nowej wartości. - metoda public class Klasa { int x; int y; void Show() { Console.WriteLine("X:"+this.x+"Y:"+this.y); } } Wywołanie metody: obiekt.metoda(parametry) - Konstruktor public class Klasa { int x; int y; public Klasa(int x, int y) { this.x = x; this.y = y; } void Show() { Console.WriteLine("X:"+this.x+"Y:"+this.y); } } - Dziedziczenie i przeciążanie metod public class Klasa { int x; int y; public Klasa(int x,int y) { this.x = x; this.y = y; } void Show() { Console.WriteLine("X:"+this.x+"Y:"+this.y); } } class Klasa2: Klasa //Klasa2 dziedziczy po Klasa { int x, y, z; public Klasa(int x,int y,int z) { this.x = x; this.y = y; this.z = z; } void Show() { Console.WriteLine("X:"+this.x+"Y:"+this.y+"Z"+this.z); } } - Obiekt ObiektObiekt jest elementem typu nazwa_klasy. Obiekty należą do typów referencyjnych. Nowy obiekt naszej klasy tworzymy: Klasa obiekt; Należy jeszcze wywołać konstruktor: obiekt = new Klasa(); Można to połączyć w jeden zapis: Klasa obiekt = new Klasa(); ------------------------------------ Interfejsy [pisane z pamięci] Nazwa interface zaczyna się od "I" (od Interface) - przyjęta konwencja w C#: interface Izapis { // lista metod do późniejszego zaimplementowania // ... } class plik : Izapis {// klasa plik dziedziczy interfejs Izapis - czyli implementuje // ... } ------------------------------------ Tablice Czemu tablice są w programowaniu obiektowym? Czytelnik, który zna inne języki takie jak C czy C++ może się zdziwić czemu tablice są w dziale na temat programowania obiektowego. Otóż w C# tablice należą do typów odnośnikowych i są użytkowane jak obiekty. - Używanie tablic int[] tablica = new int[10]; tablica[0]=1; tablica[9]=10; int[] tablica = {1,2,3,4,5}; - Tablica wielowymiarowa: int[,] tablica = new int[2,2]; tablica[1,0]=1; int[,] tablica2 = {{1,2},{3,4}}; - Tablice nieregularne Ciekawostką w C# są tablice wielowymiarowe, w których jeden z wymiarów może być zmienny. Podajemy jedynie pierwszy wymiar a drugi pomijamy: int[][] tablica = new int[3][]; tablica[0]= new int[4]; tablica[1]=new int[2]; tablica[2]=new int[8]; ------------------------------------------------- Wyjątki Wyjątki to mechanizm w programowaniu obiektowym pozwalający łatwo wyłapać błędy. Uwalnia to nas od specjalnych zmiennych i wielu instrukcji warunkowych, żeby sprawdzać czy nastąpił błąd. Jeśli nasz program nie ma w kodzie obsługi wyjątków to w pewnym sensie obsługuje je za nas framework tzn. wypisze komunikat, że nastąpił nieobsłużony wyjątek podając jego nazwę, np. IndexOutOfRangeException (w tłumaczeniu: wyjątek poza zasięgiem indeksu). Do obsługi wyjątków używamy bloku try...catch : try { //blok, w którym może nastąpić wyjątek } catch(TypWyjątku identyfikatorWyjątku) { //instrukcje do wykonania jeśli wyjątek nastąpi w czasie wykonywania kodu z bloku try } finally { //instrukcje które wykonają się niezależnie od tego czy wyjątek zostanie wyrzucony czy nie //blok finally można pominąć } Oczywiście można umieścić więcej bloków catch jeśli chcemy. Każdy wtedy będzie się zajmował innym typem wyjątków. Należy pamiętać, że istnieje hierarchia wyjątków: * Exception * SystemException * IndexOutOfRangeException Należy wyjątki obsługiwać od najniższych do najwyższych w hierarchii. Jeśli pomieszamy hierarchię to kompilator zgłosi błąd, że ten sam wyjątek chcemy obsłużyć drugi raz. - Przykład using System; public class main { public static void Main() { int[] tablica = {1,2,3,4,5} try { tablica[5]=6; } catch(IndexOutOfRangeException) { Console.WriteLine("Nastąpiło odwołanie poza tablicę!!!"); } } } - Wyrzucanie wyjątków Możemy również sami wyrzucać wyjątki. Robimy to za pomocą instrukcji throw: using System; class Program { void KupZiemniaki(int ile) { if(ile < 0) { //nie możemy kupić ujemnej liczby czegoś więc rzucamy wyjątek //po wykonaniu instrukcji throw program wyjdzie z funkcji KupZiemniaki i //dalszy kod się nie wykona throw new Exception("Nie można kupić ujemnej liczby ziemniaków"); } //... } public static void Main() { Console.WriteLine("Ile ziemniaków chcesz kupić?"); int ilosc = int.Parse(Console.ReadLine()); try { KupZiemniaki(ilosc); } catch(Exception ex) { Console.WriteLine("Wystąpił błąd przy kupowaniu ziemniaków!") } } } ------------------------------------------------- Interfejsy Interfejsy są mechanizmem zastępującym dziedziczenie wielokrotne. Interfejsy są implementowane przez klasę (zapis taki sam jak przy dziedziczeniu). Każda klasa może implementować wiele interfejsów. Należy pamiętać, że zgodnie z notacją węgierską języka C# przyjęto nazywanie interfejsów INazwa. Pozwala to jednoznacznie stwierdzić, że mamy do czynienia z interfejsem o nazwie Nazwa. Przykład: interface IShow { void Show(); } public class Klasa :IShow { int x; void Show() { Console.WriteLine(x); } } Jak zauważyliście w przykładzie w interfejsie nie ma kodu metody Show. W interfejsie nie można zdefiniować metody, dopiero klasa, która implementuje ten interfejs ma zawierać kod metody. W innych wypadkach wywoła to błąd. ------------------------------------------------- GUI Teraz utworzymy naszą pierwszą aplikację okienkową. Do tego celu potrzebna nam jest biblioteka System.Windows.Forms zawarta w .NET Frameworku. Oto nasza aplikacja okienkowa: using System; using System.Windows.Forms; public class main { public static void Main() { Application.Run(new Form()); } } Uruchamiając naszą aplikację zauważymy pewien nieprzyjemny szczegół - pod okienkiem jest konsolka. To dlatego, że do parametrów kompilacji nie dopisaliśmy /t:winexe : csc /t:winexe program.cs Teraz nie ma konsolki pod naszym oknem. Teraz wyświetlimy okno o ustalonym przez nas rozmiarze: using System; using System.Windows.Forms; public class Okno:Form { public Okno() { this.Width=320; this.Height=240; } public static void Main() { Application.Run(new Okno()); } } ------------------------------------------------- Delegaty i zdarzenia - Zdarzenia Zdarzenia można traktować jako wysokopoziomowe przerwania. Służą do interakcji programu z użytkownikiem. Dzięki nim nasz program odpowiednio zareaguje na przykład na kliknięcie myszką na przycisk. W tym przykładzie okno ma przycisk na którego kliknięcie reaguje: using System; using System.Windows.Forms; public class Okno:Form { Button przycisk = new Button(); public Okno() { this.Width=320; this.Height=240; przycisk.Top=50; przycisk.Left=100; przycisk.Text="Kliknij"; EventHandler eh = new EventHandler(this.PrzyciskClicked); przycisk.Click += eh; this.Controls.Add(przycisk); } public void PrzyciskClicked(Object sender, EventArgs e) { MessageBox.Show("Tekst komunikatu"); } } public class main { public static void Main() { Application.Run(new Okno()); } } --------------------------------------------------------------------------------------------