• Nie Znaleziono Wyników

Programowanie w środowiskach graficznych

N/A
N/A
Protected

Academic year: 2021

Share "Programowanie w środowiskach graficznych"

Copied!
39
0
0

Pełen tekst

(1)

Programowanie w

środowiskach graficznych

Wykład 4 Język C# cd

(2)

Wyjątki

 Służą do raportowania i obsługi sytuacji wyjątkowych (błędów, które można w jakiś sposób naprawić).

 Instrukcje, które mogą się z jakichś przyczyn nie udać, jak np.

• pobieranie danych od użytkownika,

• niepewne rzutowanie,

• operacje wejścia/wyjścia,

• alokację dużej ilości pamięci obudowujemy blokiem try.

object o2 = null;

try {

int i2 = (int)o2; // Casting Error }

(3)

Hierarchia klas wyjątków w C#

(4)

Wyjątki – catch, finally, throw

 Bloki catch przechwytują rzucony wyjątek i starają się go obsłużyć (lub zaraportować użytkownikowi);

 Pierwszy catch pasujący typem obsługuje wyjątek;

 Blok finally służy do końcowych porządków (np. zwolnienie zasobów);

 throw: słowo kluczowe umożliwiające (niekiedy ponowne) zgłoszenie wyjątku.

catch (FileNotFoundException e) {

// FileNotFoundExceptions are handled here.

}

catch (IOException e) {

if (e.Source != null)

Console.WriteLine("IOException source: {0}", e.Source);

throw;

}

(5)

Wyjątki – catch

Dopuszczalne jest użycie samego catch

try { …

} catch { …

}

(6)

Wskazana jest odpowiednia kolejność catch

try {

… }

catch (Exception exception) { …

} catch (IOException ioexception)

{ // tutaj nigdy nie dojdziemy, bo IOException jest // specjalizacją Exception, więc poprzedni catch // wyłapie też każdy wyjątek klasy IOException

(7)

Odpowiedniki wskaźników do funkcji z C++

Delegaty

public delegate int KtoryMniejszy (object o1, object o2);

KtoryMniejszyPorownanie += new KtoryMniejszy (FunkcjaPorownawcza);

public int FunkcjaPorownawcza (object o1, object o2) { return (o1>o2);

}

Tab.sort(Porownanie);

(8)

Delegaty i zdarzenia

 Delegaty są wykorzystywane do obsługi zdarzeń. Visual Studio automatycznie je deklaruje i wrzuca do pliku designera, np.

Form1.Designer.cs

delegate void EventHandler (object sender, EventArgs e);

button1.Click += new EventHandler (bSubmit_Click);

void bSubmit_Click(object sender, EventArgs e) { Button nadawca = sender as Button;

… }

(9)

Generyczność

(programowanie generyczne)

Generyczność pozwala klasom, strukturom, interfejsom, delegatom i metodom być

sparametryzowanym przez typ.

 Mechanizm podobny do szablonów w C++.

(10)

Dlaczego generyczność?

Przykład: stos obiektów dowolnej klasy.

Kompilator „nie wie”, jakiej klasy będą obiekty na stosie

Wymaga więc jawnego rzutowania, by wykonać kod specyficzny dla rzeczywistej klasy obiektu.

public class Stack{object[] items;int count;

public void Push(object item) {...}

public object Pop() {...}}

Stack stack = new Stack(); stack.Push(new Customer ("Nowak"));

Customer c = (Customer) stack.Pop();

c.obsłużKlienta();

(11)

A teraz to samo generycznie: parametryzujemy stos typem T i tworzymy stos Customer-ów:

Rzutowanie może być niejawne, bo kompilator wie, że na stosie wszystkie obiekty muszą być klasy Customer.

public class Stack<T>

{ T[] items;

int count;

public void Push(T item) {...}

public T Pop() {...}

}

Stack<Customer> stack = new Stack<Customer>();stack.Push(new Customer(„Adam Słodowy”));

… Customer serviced = stack.Pop();

serviced.obsłużKlienta();

(12)

Generyczność – dwa typy

Tutaj używamy napisów (klasa string) do indeksowania obiektów klasy Customer (tzw. tablica asocjacyjna).

public class Dictionary<K,V>

{ public void Add(K key, V value) {...}

public V this[K key] {...}}

Dictionary<string,Customer> dict=new Dictionary<string,Customer>();

dict.Add("Pit", new Customer("Peter Hall"));

Customer c = dict["Pit"];

}

(13)

Generyczność - kompilacja

 Kompiluje się do IL (instrukcje i metadane)

Proces tworzenia – generic type instantion

 Po jednej instancji dla każdego

używanego w kodzie typu prostego

 Jedna instancja dla typów referencyjnych

(14)

Generyczność – ograniczenia na parametry (1/4)

Kompilator sygnalizuje błędem, że nieznana mu klasa K prawdopodobnie nie obsługuje porównań (wywołań CompareTo()).

public class Dictionary<K,V>{

public void Add(K key, V value) {...

if (key.CompareTo(x) < 0) // błąd kompilacji {...}

} }

(15)

I rozwiązanie: jawne rzutowanie

Generyczność – ograniczenia na parametry (2/4)

public class Dictionary<K,V>{

public void Add(K key, V value) {

...

if (((IComparable)key).CompareTo(x) <0) {...}

...

} }

(16)

II rozwiązanie: ograniczenia na parametry generyczne

Generyczność – ograniczenia na parametry (3/4)

public class Dictionary<K, V> where K : IComparable {

public void Add(K key, V value){...

if (key.CompareTo(x) < 0) {...}...}

}

(17)

Ograniczenia mogą dotyczyć wielu interfejsów, jednej klasy, a także konstruktora new():

Generyczność – ograniczenia na parametry (4/4)

public class EntityTable<K, E>

where K : IComparable<K>, IPersistable where E : Entity, new()

{

public void Add(K key, E entity){...

if (key.CompareTo(x) < 0) {...}...}

}

(18)

Metody generyczne 1/2

 Możemy parametryzować także metody:

void PushMultiple<T> (Stack<T> stack, params T[] values) {

foreach (T value in values) stack.Push(value);

} ...

Stack<int> stack = new Stack<int>();

PushMultiple<int>(stack, 1, 2, 3, 4);

(19)

Metody generyczne 2/2

type inferencing – wywołanie metody z odpowiednim typem generycznym na podstawie dedukcji parametrów:

tak jak dla klas możemy wprowadzać też ograniczenia dla metod:

Stack<int> stack = new Stack<int>();

PushMultiple(stack, 1, 2, 3, 4); //wywołanie dla int

public class MyClass{

public void SomeMethod<T>(T t) where T :IComparable<T>

{ ...

}

(20)

Typy generyczne i rzutowanie 1/3

Niejawnie możemy rzutować do object i do typów występujących w

ograniczeniach:

class MyClass<T> where T : BaseClass,ISomeInterface {

void SomeMethod(T t) {

ISomeInterface obj1 = t;

BaseClass obj2 = t;

object obj3 = t;

} }

(21)

 Jawnie rzutować możemy tylko do interfejsów:

Typy generyczne i rzutowanie 2/3

class MyClass<T> {

void SomeMethod(T t) {

ISomeInterface obj1 = (ISomeInterface)t; // Compiles SomeClass obj2 = (SomeClass)t; // ERROR!

} }

(22)

 Możemy ominąć to ograniczenie

używając zmiennej pomocniczej typu object:

używać operatorów is i as.

Typy generyczne i rzutowanie 3/3

class MyClass<T> {

void SomeMethod(T t) {

object temp = t;

SomeClass obj = (SomeClass)temp;

} }

}

(23)

Dziedziczenie i generics 1/2

Jeżeli klasa dziedziczy z klasy generycznej to musi być podany konkretny typ jako parametr:

public class BaseClass<T>{...}

public class SubClass : BaseClass<int>{...}

Chyba że klasa i podklasa są sparametryzowane tym samym parametrem:

public class SubClass<T> : BaseClass<T> {...}

(24)

Dziedziczenie i generics 2/2

 Przy dziedziczeniu należy powtarzać ograniczenia w podklasach:

public class BaseClass<T> where T : ISomeInterface {...}

public class SubClass<T> : BaseClass<T> where T : ISomeInterface{...}

To samo dotyczy metod wirtualnych:

public class BaseClass{

public virtual void SomeMethod<T>(T t) where T : new() {...}

}

public class SubClass : BaseClass{

public override void SomeMethod<T>(T t) where T : new() {...}

} 24

(25)

Generics i delegaty

 Tak jak klasy struktury i interfejsy możemy sparametryzować typem generycznym także delegaty:

public delegate void GenericDelegate<T>(T t);

public class MyClass{

public void SomeMethod(int number) {...}

}

MyClass obj = new MyClass();

GenericDelegate<int> del;

del = new GenericDelegate<int>(obj.SomeMethod);

del(3);

(26)

Kolekcje generyczne i niegeneryczne

 System.Collections.Generics i

odpowiedniki System.Collections

Comparer<T> Comparer

Dictionary<K,T> HashTable

List<T> ArrayList

Queue<T> Queue

SortedDictionary<K,T> SortedList

Stack<T> Stack

(27)

Metody anonimowe 1/3

Standardowy handler zdarzenia w osobnej metod

class InputForm: Form { ListBox listBox;

TextBox textBox;

Button addButton;

public MyForm() {

listBox = new ListBox(...);

textBox = new TextBox(...);

addButton = new Button(...);

addButton.Click += new EventHandler(AddClick);

}

void AddClick(object sender, EventArgs e) { listBox.Items.Add(textBox.Text);

}

(28)

Metody anonimowe 2/3

Ten sam przykład z użyciem metody anonimowej:

Kod jest krótszy, ale nie możemy używać tego samego handlera dla wielu kontrolek

class InputForm: Form{

ListBox listBox;

TextBox textBox;

Button addButton;

public MyForm() {

listBox = new ListBox(...);

textBox = new TextBox(...);

addButton = new Button(...);

addButton.Click += delegate{listBox.Items.Add(textBox.Text);};

} }

(29)

Metody anonimowe 3/3

Możemy także używać metod anonimowych do wpisywania funkcji “in-line”

delegate double Function (double x);

class Test{

static double[] Apply(double[] a, Function f) { … }

static double[] MultiplyAllBy(double[] a, double factor) {

return Apply(a, delegate(double x) { return x*factor; });

}

static void Main() {

double[] a = {0.0, 0.5, 1.0};

double[] squares = Apply(a, delegate(double x) { return x*x; });

double[] doubles = MultiplyAllBy(a, 2.0);

(30)

Iteratory 1/3

Żeby można było użyć pętli foreach na

kolekcji, to kolekcja musi spełniać warunki:

 Kolekcja musi implementować interfejs IEnumerable.

 Kolekcja musi mieć bezparametrową

metodę GetEnumerator().

(31)

Iteratory 2/3

„Numeratory” są trudne do zaimplementowania.

Sprawę ułatwiają nam ITERATORY:

public class Stack<T>: IEnumerable<T>

{

T[] items;

int count;

public void Push(T data) {...}

public T Pop() {...}

public IEnumerator<T> GetEnumerator() {

for (int i = count – 1; i >= 0; --i) { yield return items[i];

} }

}

Mamy też do dyspozycji instrukcję yield break

(32)

Iteratory 3/3

Możemy także zdefiniować kilka iteratorów dla 1 kolekcji:

public class Stack<T>: IEnumerable<T>

{

public IEnumerator<T> GetEnumerator() { for (int i = count – 1; i >= 0; --i) {

yield return items[i];

} }

public IEnumerable<T> TopToBottom { get {

return this;

} }

public IEnumerable<T> BottomToTop { get {

for (int i = 0; i < count; i++) { yield return items[i];

}

}

(33)

Iteratory 3/3 cd..

Użycie:

class Test {

static void Main() {

Stack<int> stack = new Stack<int>();

for (int i = 0; i < 10; i++) stack.Push(i);

foreach (int i in stack.TopToBottom) Console.Write("{0} ", i);

foreach (int i in stack.BottomToTop) Console.Write("{0} ", i);

}

}

(34)

Klasy częściowe 1/2

Podział zawartości 1 klasy w więcej niż jednym pliku np:

plik1.cs

public partial class Customer {

private int id;

private string name;

private string address;

private List<Order> orders;

public Customer() { ...

}

}

(35)

Klasy częściowe 2/2

 Plik2.cs

public partial class Customer {

public void SubmitOrder(Order order) { orders.Add(order);

}

public bool HasOutstandingOrders() { return orders.Count > 0;

}

}

(36)

Nullable type 1/3

 Wprowadza dla wszystkich typów prostych dodatkową możliwą wartość null.

 int? Jest to typ wbudowany + wartość null.

 HasValue - właściwość, która zwraca nam

true or false jeżeli typ jest nullable lub nie.

(37)

Nullable type 2/3

 Operacje arytmetyczne z null-em dają null

 Operatory >,<,<=, >= zwracają false, jeżeli któryś z argumentów jest null.

 Nowy operator ??

a??b – rezultatem jest a jeżeli a jest

not-null i b w przeciwnym przypadku.

(38)

Nullable type 3/3

 Przykład:

int? x = GetNullableInt();

int? y = GetNullableInt();

int? z = x ?? y;

int i = z ?? -1;

 Operator ten działa też dla typów referencyjnych:

string s = GetStringValue();

Console.WriteLine(s ?? "Unspecified");

(39)

Podsumowanie

 Duży wachlarz konstrukcji.

 Różne paradygmaty (komponentowy, obiektowy, funkcyjny, proceduralny)

 Uznawany za najlepszy język do

programowania na platformie .NET

Cytaty

Powiązane dokumenty

Jednak język programowania wysokiego poziomu nie jest jasny dla komputera, który rozumie jedynie ciągi zer i jedynek. Dlatego musimy posłużyć się aplikacją,

Tworzenie aplikacji z użyciem Windows Forms: podstawowe informacje – aplikacja, formularze, zdarzenia, okna dialogowe.. Kontrolki dostępne w

 tylko w tym formacie zasoby mogą być dołączone do assembly, pozostałe formaty muszą być

Możemy też sprawdzać, czy obiekt implementuje wybrany interfejs:. if (obiekt

 GDI+ skaluje obrazki w taki sposób, by ich fizyczny rozmiar na urządzeniu używanym do rysowania był jak najbliższy. fizycznemu rozmiarowi na urządzeniu, na którym zostały

• Klasy dziedziczące po klasie Exception są typami wyjątków, które automatycznie obsługuje Java lub program przy jawnym przechwytywaniu i obsłudze wyjątków w

Determinuje także sposób życia człowieka, począwszy od biologicznego funkcjonowania jego organizmu, poprzez proces kształtowania się jego tożsamości płciowej, aż

Spektakl jest mocno osadzony w tekście, do tego stopnia, że wszystko, co się dzieje, zawiera się w tym, co wypowiadane – niczym w tragedii antycznej.. Materia językowa