Скачать презентацию C Visual Studio 2010 NET 4 0 Скачать презентацию C Visual Studio 2010 NET 4 0

fb0390e1fef288136a6047ac0295505d.ppt

  • Количество слайдов: 166

C#, Visual Studio 2010, . NET 4. 0 dr inż. Marcin Radom Instytut Informatyki, C#, Visual Studio 2010, . NET 4. 0 dr inż. Marcin Radom Instytut Informatyki, Politechnika Poznańska laboratorium Programowania Wizualnego 1

Część I: Wstęp, C# i. NET 2 Część I: Wstęp, C# i. NET 2

Tajemnicze skróty z. NET CLR – Common Language Runtime CTS – Common Type System Tajemnicze skróty z. NET CLR – Common Language Runtime CTS – Common Type System CLS – Common Language Specification JIT(ter) – Just-in-time Compiler CIL – Common Intermediate Language (przez JIT) . NET Metadata . NET Asembly Manifest 3

Użyteczne programy ildasm. exe ( Program FilesMicrosoft SDKs7. 0 Abin ) Reflector ( http: Użyteczne programy ildasm. exe ( Program FilesMicrosoft SDKs7. 0 Abin ) Reflector ( http: //www. redgate. com/products/reflector ) 4

Część II: Programowanie w C# 5 Część II: Programowanie w C# 5

Kompilator konsolowy csc. exe ( dostęp np. poprzez link w zainstalowanym folderze menu Start Kompilator konsolowy csc. exe ( dostęp np. poprzez link w zainstalowanym folderze menu Start ) Parametry: /out /target: exe (library, module, winexe) C: csc. exe /target: exe Program. cs C: csc *. cs C: csc /out: Moj. Program. exe @Program. rsp 6

Pliki *. rsc # External assembly references. /r: System. Windows. Forms. dll # Output Pliki *. rsc # External assembly references. /r: System. Windows. Forms. dll # Output and files to compile (using wildcard syntax). /target: exe /out: Program. exe *. cs csc. rsp ( WindowsMicrosoft. NETFramework ) 7

Inne programy Notepad++ http: //notepad-plus. sourceforge. net Sharp. Develop http: //www. sharpdevelop. com Mono Inne programy Notepad++ http: //notepad-plus. sourceforge. net Sharp. Develop http: //www. sharpdevelop. com Mono http: //www. mono-project. com Visual C#2010 Express 8

Cechy MS Visual Studio 2010 Solution Explorer Utility Referencing External Assemblies Project Properties Class Cechy MS Visual Studio 2010 Solution Explorer Utility Referencing External Assemblies Project Properties Class View Utility Object Browser Utility Integrated Support for Code Refactoring Code Expansion and Surround With Technology Visual Class Designer 9

Część III: Podstawy (1) 10 Część III: Podstawy (1) 10

Hello World w C# using System; System. Collections. Generic; System. Linq; System. Text; namespace Hello World w C# using System; System. Collections. Generic; System. Linq; System. Text; namespace Console. Application. Exemplar { class Program { static void Main(string[] args) { Console. Write. Line("Hello World!"); Console. Write. Line(); Console. Read. Line(); } } } 11

Przetwarzanie parametrów wejściowych for(int i = 0; i < args. Length; i++) Console. Write. Przetwarzanie parametrów wejściowych for(int i = 0; i < args. Length; i++) Console. Write. Line("Arg: {0}", args[i]); -wyświetli listę parametrów startowych foreach(string arg in args) Console. Write. Line("Arg: {0}", arg); -jak wyżej string[] the. Args = Environment. Get. Command. Line. Args(); foreach(string arg in the. Args) Console. Write. Line("Arg: {0}", arg); -jak wyżej 12

Obiekty Environment, Console – i ich przydatne metody (do sprawdzenia we własnym zakresie) Environment. Obiekty Environment, Console – i ich przydatne metody (do sprawdzenia we własnym zakresie) Environment. OSVersion (Processor. Count, Version) Console. Write. Line (Read. Line, Beep(), Background. Color, Buffer. Height, Width, Title, Clear, etc. ) Console. Write. Line( „{0} oraz {0}”, 9 ); {0: c} {0: d 9} {0: f 3} etc… 13

Zmienne float L 1 = 7. 4 F; (bez F – double) long L Zmienne float L 1 = 7. 4 F; (bez F – double) long L 2 = 10 D; (bez D – int) ponieważ liczby w C# to struktury, można wykonać operacje: ◦ 12. Get. Hash. Code(); ◦ 12. Equals(23); ◦ 12. To. String(); //12 //FALSE //12 ◦ double. Max. Value ◦ double. Positive. Infinity, etc… 14

Big. Integer – na naprawdę duże liczby System. Numerics (References->Add reference ->zakładka. NET ) Big. Integer – na naprawdę duże liczby System. Numerics (References->Add reference ->zakładka. NET ) static void Use. Big. Integer() { Console. Write. Line("Use Big. Integer: "); Big. Integer dlug = Big. Integer. Parse(„ 10000000000000000999"); Console. Write. Line("{0}", dlug. Is. Even); Console. Write. Line("{0}", dlug. Is. Power. Of. Two); Big. Integer dlug. USA = Big. Integer. Multiply(dlug, Big. Integer. Parse("10000000000000000"); Console. Write. Line("{0}", dlug. USA); } 15

Łańcuchy String – czyli to co wszyscy znają Łańcuchy dosłowne (verbatim) @ wszystko wewnątrz Łańcuchy String – czyli to co wszyscy znają Łańcuchy dosłowne (verbatim) @ wszystko wewnątrz jest traktowane jako łańcuch, nawet (a raczej: zwłaszcza) wszystkie znaki specjalne jak / ” itd. String. Builder (System. Text) - jeżeli chcemy oszczędzać pamięć 16

Rozszerzanie / zawężanie typów danych implicit / explicit – sposób przypisywania zmiennych różnych typów Rozszerzanie / zawężanie typów danych implicit / explicit – sposób przypisywania zmiennych różnych typów – pierwszy to domyślny, nie działa przy przekraczaniu zakresu typu, drugi wprost mówi kompilatorowi, że wiemy co robimy, np. zmienna_int = (int)wielki_float; checked / unchecked Opcje domyślne dla środowiska w kwestiach powyższych: Properties -> Build -> [Advanced]Button 17

Zmienna typu zmienna, czyli typ ’var’ var cos = 0; cos. Get. Type(). Name Zmienna typu zmienna, czyli typ ’var’ var cos = 0; cos. Get. Type(). Name //wynik: int var my. Int = 0; var my. Bool = true; var my. String = "Time, marches on. . . "; Błędy: ◦ ◦ public var cos = 0; public var Metoda(var x); var cos; cos=0; var obiekt = null; ◦ var? nic = nowy. Obiekt(); ◦ var? blad = 12; 18

(Elementarne) konstrukcje języka Pętle: foreach ; for while ; do / while Instrukcje warunkowe: (Elementarne) konstrukcje języka Pętle: foreach ; for while ; do / while Instrukcje warunkowe: if / else switch () { case 1: …. break; case 2: …. break default: …. break } 19

Część IV: Podstaw ciąg dalszy 20 Część IV: Podstaw ciąg dalszy 20

Parametry argumentów metod: out, ref, params OUT – wywoływana metoda MUSI zwrócić wartość REF Parametry argumentów metod: out, ref, params OUT – wywoływana metoda MUSI zwrócić wartość REF – wywoływana metoda może trwale zmienić wartość PARAMS – w skrócie(wielkim): nieokreślona liczba zmiennych pewnego typu public static void Swap. Strings(ref string s 1, ref string s 2) { string temp. Str = s 1; s 1 = s 2; s 2 = temp. Str; } static void Main(string[] args) { Console. Write. Line("*****"); string s 1 = "Flip"; string s 2 = "Flop"; Console. Write. Line("Before: {0}, {1} ", s 1, s 2); Swap. Strings(ref s 1, ref s 2); Console. Write. Line("After: {0}, {1} ", s 1, s 2); Console. Read. Line(); } Before: Flip, Flop After: Flop, Flip 21

params static double Srednia(params double[] values) { Console. Write. Line(„Ile: {0} params static double Srednia(params double[] values) { Console. Write. Line(„Ile: {0}", values. Length); double sum = 0; if (values. Length == 0) return sum; for (int i = 0; i < values. Length; i++) sum += values[i]; return (sum / values. Length); } double average; average = Srednia(4. 0, 3. 2, 5. 7, 64. 22, 87. 2); Console. Write. Line("Average of data is: {0}", average); double[] data = { 4. 0, 3. 2, 5. 7 }; average = Srednia(data); Console. Write. Line("Average of data is: {0}", average); 22

Parametry opcjonalne (. NET 4. 0) static void Enter. Log. Data(string message, string owner Parametry opcjonalne (. NET 4. 0) static void Enter. Log. Data(string message, string owner = "Programmer") { Console. Beep(); Console. Write. Line("Error: {0}", message); Console. Write. Line("Owner of Error: {0}", owner); } static void Main(string[] args) { Enter. Log. Data(„ERROR"); Enter. Log. Data(„ERROR", „Ja"); Console. Read. Line(); } 23

Wywoływanie metod z nazwanymi parametrami (. NET 4. 0) - Kolejność wywołania: dowolna static Wywoływanie metod z nazwanymi parametrami (. NET 4. 0) - Kolejność wywołania: dowolna static void Main(string[] args) { Metoda(message: "Test", text. Color: Console. Color. Dark. Red, Background. Color: Console. Color. White); Metoda(background. Color: Console. Color. Green, Message: "Testing. . . ", text. Color: Console. Color. Dark. Blue); Console. Read. Line(); } static void Metoda(Console. Color text. Color, Console. Color background. Color, string message) {. . . } 24

Przeciążenie metod static int Add(int x, int y) { return x + y; } Przeciążenie metod static int Add(int x, int y) { return x + y; } static double Add(double x, double y) { return x + y; } static long Add(long x, long y) { return x + y; } static void Main(string[] args) { Console. Write. Line(""); Console. Write. Line(Add(10, 10)); Console. Write. Line(Add(9000000, 9000000)); Console. Write. Line(Add(4. 3, 4. 4)); Console. Read. Line(); } 25

Tablice int[] my. Ints = new int[3]; my. Ints[0] = 100; my. Ints[1] = Tablice int[] my. Ints = new int[3]; my. Ints[0] = 100; my. Ints[1] = 200; my. Ints[2] = 300; string[] string. Array = new string[] {"raz", "dwa", "trzy"}; Console. Write. Line("Elementów: {0}", string. Array. Length); bool[] bool. Array = { false, true }; Console. Write. Line("Elementów: {0}", bool. Array. Length); int[] int. Array = new int[4] { 20, 22, 23, 0 }; Console. Write. Line("Elementów: {0}", int. Array. Length); Console. Write. Line(); 26

Implicit Array Initialization. "); var a" src="https://present5.com/presentation/fb0390e1fef288136a6047ac0295505d/image-27.jpg" alt="Tablice typu var Tablice obiektów Console. Write. Line("=> Implicit Array Initialization. "); var a" /> Tablice typu var Tablice obiektów Console. Write. Line("=> Implicit Array Initialization. "); var a = new[] { 1, 100, 1000 }; Console. Write. Line("a is a: {0}", a. To. String()); var b = new[] { 1, 1. 5, 2, 2. 5 }; Console. Write. Line("b is a: {0}", b. To. String()); var c = new[] { "hello", null, "world" }; Console. Write. Line("c is a: {0}", c. To. String()); Console. Write. Line(); object[] my. Objects = new object[4]; my. Objects[0] = 42; my. Objects[1] = false; my. Objects[2] = new Date. Time(2012, 22); my. Objects[3] = "Form & Void"; foreach (object obj in my. Objects) { Console. Write. Line("Type: {0}, Value: {1}", obj. Get. Type(), obj); } 27

Tablica postrzępiona (jagged array) static void Jagged. Multidimensional. Array() { int[][] my. Jag. Array Tablica postrzępiona (jagged array) static void Jagged. Multidimensional. Array() { int[][] my. Jag. Array = new int[5][]; for (int i = 0; i < my. Jag. Array. Length; i++) my. Jag. Array[i] = new int[i + 7]; for (int i = 0; i < 5; i++) { for (int j = 0; j < my. Jag. Array[i]. Length; j++) Console. Write(my. Jag. Array[i][j] + " "); Console. Write. Line(); } 0000000000 000000 28

Typy wyliczeniowe enum Emp. Type : byte { Manager = 10, Grunt = 1, Typy wyliczeniowe enum Emp. Type : byte { Manager = 10, Grunt = 1, Contractor = 100, Vice. President = 999 } static void Ask. For. Bonus(Emp. Type e) { switch (e) { case Emp. Type. Manager: Console. Write. Line(„A może akcje? "); break; case Emp. Type. Grunt: static void Main(string[] args) Console. Write. Line(„Bardzo zabawne. . . "); { break; Emp. Type emp = Emp. Type. Contractor; case Emp. Type. Contractor: Ask. For. Bonus(emp); Console. Write. Line(„Ty zdzierco. . . "); Console. Read. Line(); break; Console. Write. Line("emp is a case Emp. Type. Vice. President: {0}. ", emp. To. String()); Console. Write. Line(„TAK JEST!”); // Wypisze "Contractor = 100". break; Console. Write. Line("{0} = {1}", } emp. To. String(), (byte)emp); } } 29

Struktury static void Main(string[] args) { Point my. Point; my. Point. X = 349; Struktury static void Main(string[] args) { Point my. Point; my. Point. X = 349; my. Point. Y = 76; my. Point. Display(); my. Point. Increment(); my. Point. Display(); Console. Read. Line(); } struct Point { public int X; public int Y; public void Increment() { X++; Y++; } public Point(int x. P, int y. P) { X = x. P; Y = y. P; } public void Display() { Console. Write. Line("X = {0}, Y = {1}", X, Y); } } 30

Inne sposoby pracy z typami (możliwe w C#) Typy wartościowe zawierające typy referencyjne ( Inne sposoby pracy z typami (możliwe w C#) Typy wartościowe zawierające typy referencyjne ( struct zawierające class ) Przekazywanie typów referencyjnych przez wartość ( public void Metoda(Person p) { … } ) Przekazywanie typów referencyjnych przez referencje ( ref ) Wiele innych 31

Typy nullable, operator ? ? int? nullable. Int = 10; double? nullable. Double = Typy nullable, operator ? ? int? nullable. Int = 10; double? nullable. Double = 3. 14; bool? nullable. Bool = null; char? nullable. Char = 'a'; int? [] array. Of. Nullable. Ints = new int? [10]; // compile-time error: string? s = "oops"; int? jakas. Liczba = Metoda() ? ? 100; // jeżeli Metoda() zwróci coś o wartości NULL, wtedy (i tylko wtedy) przypisz wartość 100 do ‘jakas. Liczba’ 32

Część V: Klasy, obiekty, etc. 33 Część V: Klasy, obiekty, etc. 33

Przykład klasy class Car { public string pet. Name; public int curr. Speed; public Przykład klasy class Car { public string pet. Name; public int curr. Speed; public void Print. State() { Console. Write. Line ("{0} jedzie {1} kmh. ", pet. Name, curr. Speed); } public void Speed. Up(int delta) { curr. Speed += delta; } class Program { static void Main(string[] args) { Car my. Car = new Car(); my. Car. pet. Name = "Audi"; my. Car. curr. Speed = 10; for (int i = 0; i <= 10; i++) { my. Car. Speed. Up(5); my. Car. Print. State(); } Console. Read. Line(); } } } 34

this public int curr. Speed; public Car(int curr. Speed) { curr. Speed = curr. this public int curr. Speed; public Car(int curr. Speed) { curr. Speed = curr. Speed; } VS: public Car(int curr. Speed) { this. curr. Speed = curr. Speed; } 35

this – wskazanie na konstruktor class Motorcycle { public int power; public string driver. this – wskazanie na konstruktor class Motorcycle { public int power; public string driver. Name; public Motorcycle() { } public Motorcycle(int intensity) : this(intensity, "") { } public Motorcycle(string name) : this(0, name) { } public Motorcycle(int pow, string name) { if(pow > 10) { pow = 10; } power = pow; driver. Name = name; } } Motorcycle c = new Motorcycle(5); najpierw wykona się najniższy konstruktor (czyli Motorcycle(int pow, string name) ), dopiero potem ten, który przyjmuje int (z powodu konstrukcji: " : this(intensity, ” ”) { } " 36

Konstruktor z domyślnymi parametrami (. NET 4. 0) public Motorcycle(int power = 0, string Konstruktor z domyślnymi parametrami (. NET 4. 0) public Motorcycle(int power = 0, string name = "") { if (power > 10) { power = 10; } this. power = intensity; driver. Name = name; } 37

static class Motorcycle { public static int ile. Motocykli; public static int liczba. Stworzonych. static class Motorcycle { public static int ile. Motocykli; public static int liczba. Stworzonych. Obiektow() { return ile. Motocykli; } } Dostępne z poziomu klasy, nie obiektu – wszystkie nowe obiekty współdzielą jedną wersję pól statycznych / metod statycznych w ramach swojej klasy. Tylko metody statyczne i pola statyczne mogą być używane wewnątrz metod statycznych – nie mają one dostępu do zwykłych pól, bo te nie istnieją na tym poziomie (żadnego „this”! ). 38

Programowanie obiektowe (OOP) Czyli co należy znać już od dawna: dziedziczenie polimorfizm hermetyczność używanie Programowanie obiektowe (OOP) Czyli co należy znać już od dawna: dziedziczenie polimorfizm hermetyczność używanie obiektów innej klasy w jeszcze innym obiekcie (jeszcze innej klasy), etc. virtual override sealed abstract 39

Modyfikatory dostępu public private ( domyślny ) protected internal (domyślny ) protected internal 40 Modyfikatory dostępu public private ( domyślny ) protected internal (domyślny ) protected internal 40

Właściwości ( properties ) class Employee{ private string emp. Name; private int emp. ID; Właściwości ( properties ) class Employee{ private string emp. Name; private int emp. ID; private float curr. Pay; public string Name { get { return emp. Name; } set { if (value. Length > 30) Console. Write. Line("Przekroczony limit znakow. "); else emp. Name = value; } } public int ID { get { return emp. ID; } set { emp. ID = value; } } public float Pay { get { return curr. Pay; } set { curr. Pay = value; } } } 41

Właściwości (seq. ) modyfikatory dostępności: public string SSN { get { return emp. SSN; Właściwości (seq. ) modyfikatory dostępności: public string SSN { get { return emp. SSN; } protected set { emp. SSN = value; } } tylko do odczytu: public string SSN { get { return emp. SSN; } } automatyczne: class Car { public string Pet. Name { get; set; } public int Speed { get; set; } public string Color { get; set; } } 42

Inicjalizator obiektów class Punkt { public int X { get; set; } public int Inicjalizator obiektów class Punkt { public int X { get; set; } public int Y { get; set; } public Punkt(int x. Val, int y. Val) { X = x. Val; Y = y. Val; } public Punkt() { } public void Show. Data() { Console. Write. Line("[{0}, {1}]", X, Y); } } Punkt final. Point = new Punkt { X = 30, Y = 30 }; Punkt final. Point 2 = new Punkt() { X = 30, Y = 30 }; Punkt pt = new Punkt(10, 16) { X = 100, Y = 100 }; //no i jakie teraz będą współrzędne? final. Point. Show. Data(); Console. Read. Line(); 43

Inicjalizator obiektów (seq. ) class Punkt { public int X { get; set; } Inicjalizator obiektów (seq. ) class Punkt { public int X { get; set; } public int Y { get; set; } public Point. Color { get; set; } public Punkt(int x. Val, int y. Val) { X = x. Val; Y = y. Val; } Punkt() { } Punkt(Point. Color pt. Color) { Color = pt. Color; } Punkt() : this(Point. Color. Blood. Red){ } public void Show. Data() { Console. Write. Line("[{0}, {1}]", X, Y); } } … Punkt gold. Point = new Punkt(Point. Color. Gold) { X = 90, Y = 20 }; 44

Stałe const public const double Pi = 3. 14; const string napis = Stałe const public const double Pi = 3. 14; const string napis = "NAPIS"; readonly public readonly double PI; … public Klasa() { PI = 3. 14; } także: static dodane do powyższych - o ile potrzebujemy stałych statycznych (np. aby móc na nich operować wewnątrz metod statycznych). 45

Część VI: Dziedziczenie i polimorfizm 46 Część VI: Dziedziczenie i polimorfizm 46

Dziedziczenie class Samochod { public readonly int limit; private int curr. Speed; public Samochod(int Dziedziczenie class Samochod { public readonly int limit; private int curr. Speed; public Samochod(int max) { limit = max; } public Samochod() { limit = 55; } public int Speed { get { return curr. Speed; } set { curr. Speed = value; if (curr. Speed > limit) { curr. Speed = limit; } } class Ciezarowka : Samochod { } 47

Dziedziczenie (seq. ) Brak wielokrotnego dziedziczenia klas (działa dla interfejsów) SEALED – zamknięcie dalszego Dziedziczenie (seq. ) Brak wielokrotnego dziedziczenia klas (działa dla interfejsów) SEALED – zamknięcie dalszego dziedziczenia z klasy, którą poprzedzimy właśnie rozkazem ‘sealed’ Załóżmy, że klasa nadrzędna ma 5 pól public arg 1 - arg 5, dziedzicząca dodała własne arg 6, wtedy konstruktor dziedziczącej, żeby się nie powtarzać może wyglądać tak: public Dziedziczaca(int arg 1, int arg 2, int arg 3, string arg 4, string arg 5, double arg 6) : base (arg 1, arg 2, arg 3, arg 4, arg 5) { pole 6 = arg 6; } 48

Typy zagnieżdżone class Zewnetrzna { public class Wewnetrzna { } private class Jeszcze. Jedna. Typy zagnieżdżone class Zewnetrzna { public class Wewnetrzna { } private class Jeszcze. Jedna. Wewnetrzna { } } Cechy: Kontrola takiej klasy (zagnieżdżonej) dostęp do private typ pomocniczy 49

Polimorfizm: virtual, override, etc. class Przyklad { private int dane = 1; public virtual Polimorfizm: virtual, override, etc. class Przyklad { private int dane = 1; public virtual void Stats() { Console. Write. Line(dane); } } class Inna : Przyklad { private int inne. Dane = 10; public override void Stats() { Console. Write. Line(inne. Dane); } } Bez słów virtual/override – wystąpi ostrzeżenia środowiska i kompilatora, ale tylko ostrzerzenie (program wciąż można kompilować). Można użyć słówka ‘new’ jako słowa środowiskowego: „odczep się, wiem co robię” – jest to tzw. cieniowanie składowych. public override sealed void Stats () { … } 50

abstract Dla klas, które nie mają być tworzone (jako obiekty), ale abstract Dla klas, które nie mają być tworzone (jako obiekty), ale " tylko " przekazywać pewną wspólną funkcjonalność dla dziedziczących (które z kolei są już tworzone jako: Obiekt = new Klasa(); W przypadku metod z klasy abstract – WYMUSZONE SĄ przeładowania ich jako override (w przeciwieństwie do przypadku samego virtual/override wewnątrz klasy nie będącej abstrakcyjną, które to rozkazy wtedy nie wymuszają niczego, tj. jeśli klasa dziedzicząca nie przeładuje takiej metody, wtedy może dojść do wywołania metody wirtualnej z klasy bazowej – niekoniecznie będzie to sensowne. Słowo abstract przed tym zabezpiecza ). Metody abstrakcyjne TYLKO w klasach abstrakcyjnych. Nie ma ciała metody, tj. zawsze konstrukcja: ◦ public abstract void Metoda ( parametry ) {} // ostatnie nawiasy konieczne, ale puste 51

as / is Kolo kolko = new Kolo(); Sprezyna x 66 = (Sprezyna)kolko; // as / is Kolo kolko = new Kolo(); Sprezyna x 66 = (Sprezyna)kolko; // error, Invalid. Cast. Exception Powyższą, mało bezpieczną konstrukcję można zastąpić: try { Hexagon hex = (Hexagon)frank; } catch (Invalid. Cast. Exception ex) { Console. Write. Line(ex. Message); } ALBO przy użyciu słowa AS: Sprezyna x 67 = kolko as Sprezyna; //a nóż-widelec się uda… if (x 67 == null) {. . . } IS - skoro słowo as pozwala tworzyć „cuda na kreacją” klas, słowo is pozwala potem ogarnąć, z jakiego rodzaju obiektem (jakiej klasy) mamy do czynienia gdzieś dalej w kodzie: if ( x 67 is kolko ) {. . . } else {. . . } 52

Klasa System. Object – pani matka WSZYSTKIEGO w języku C# public class Object { Klasa System. Object – pani matka WSZYSTKIEGO w języku C# public class Object { // Virtual members. public virtual bool Equals(object obj); protected virtual void Finalize(); public virtual int Get. Hash. Code(); public virtual string To. String(); // Instance level, non-virtual members. public Type Get. Type(); protected object Memberwise. Clone(); // Static members. public static bool Equals(object obj. A, object obj. B); public static bool Reference. Equals (object obj. A, object obj. B); } Krótko i zwięźle: WSZYSTKO, każda klasa, dziedziczy z System. Object albo bezpośrednio, albo pośrednio. 53

Część VII: Strukturalna obsługa wyjątków 54 Część VII: Strukturalna obsługa wyjątków 54

System. Exception – główna klasa, z której dziedziczą wyjątki public class Exception : ISerializable, System. Exception – główna klasa, z której dziedziczą wyjątki public class Exception : ISerializable, _Exception { // Public constructors public Exception(string message, Exception inner. Exception); public Exception(string message); public Exception(); // Methods public virtual Exception Get. Base. Exception(); public virtual void Get. Object. Data(Serialization. Info info, Streaming. Context context); // Properties public virtual IDictionary Data { get; } public virtual string Help. Link { get; set; } public Exception Inner. Exception { get; } public virtual string Message { get; } public virtual string Source { get; set; } public virtual string Stack. Trace { get; } public Method. Base Target. Site { get; } } 55

Tworzenie własnego wyjątku Exception ex = new Exception(string. Format( Tworzenie własnego wyjątku Exception ex = new Exception(string. Format("{0} wylecial w powietrze!", name)); ex. Help. Link = "http: //www. costam. pl"; ex. Data. Add("Czas", string. Format("Czas: {0}", Date. Time. Now)); ex. Data. Add("Powod", "Bo masz pecha. "); throw ex; // ręczne odpalenie wyjątku 56

Obsługa wyjątków try {. . . ; //tutaj coś eksplodowało } catch (Exception e) Obsługa wyjątków try {. . . ; //tutaj coś eksplodowało } catch (Exception e) { Console. Write. Line("Member name: {0}", e. Target. Site); Console. Write. Line("Class defining member: {0}", e. Target. Site. Declaring. Type); Console. Write. Line("Member type: {0}", e. Target. Site. Member. Type); Console. Write. Line("Message: {0}", e. Message); Console. Write. Line("Source: {0}", e. Source); Console. Write. Line("Stack: {0}", e. Stack. Trace); Console. Write. Line("Help Link: {0}", e. Help. Link); Console. Write. Line("n-> Custom Data: "); if (e. Data != null) { foreach (Dictionary. Entry de in e. Data) Console. Write. Line("-> {0}: {1}", de. Key, de. Value); } } 57

Główne klasy wyjątków: System. Exception : Exception System. Application. Exception: Exception 58 Główne klasy wyjątków: System. Exception : Exception System. Application. Exception: Exception 58

Własne wyjątki – przykład 2 public class Car. Is. Dead. Exception : Application. Exception Własne wyjątki – przykład 2 public class Car. Is. Dead. Exception : Application. Exception { private string message. Details = String. Empty; public Date. Time Error. Time. Stamp { get; set; } public string Cause. Of. Error { get; set; } public Car. Is. Dead. Exception() { } public Car. Is. Dead. Exception(string message, string cause, Date. Time time) { message. Details = message; Cause. Of. Error = cause; Error. Time. Stamp = time; } public override string Message { get { return string. Format("Car Error Message: {0}", message. Details); } } } WYRZUCENIE WYJĄTKU: Car. Is. Dead. Exception ex = new Car. Is. Dead. Exception (string. Format("{0} wybuchl!", name), „Bo masz pecha", Date. Time. Now); ex. Help. Link = "http: //www. allegro. pl"; throw ex; 59

Jeszcze lepiej: [global: : System. Serializable] public class Car. Is. Dead. Exception : Application. Jeszcze lepiej: [global: : System. Serializable] public class Car. Is. Dead. Exception : Application. Exception { public Car. Is. Dead. Exception() { } public Car. Is. Dead. Exception(string message) : base(message) { } public Car. Is. Dead. Exception(string message, Exception inner) : base(message, inner) { } protected Car. Is. Dead. Exception( System. Runtime. Serialization. Info info, System. Runtime. Serialization. Streaming. Context context) : base(info, context) { } public Date. Time Error. Time. Stamp { get; set; } public string Cause. Of. Error { get; set; } public Car. Is. Dead. Exception(string message, string cause, Date. Time time) : base(message) { Cause. Of. Error = cause; Error. Time. Stamp = time; } } 60

Obsługa wielu wyjątków try {. . . } catch (Car. Is. Dead. Exception e) Obsługa wielu wyjątków try {. . . } catch (Car. Is. Dead. Exception e) { Console. Write. Line(e. Message); } catch (Argument. Out. Of. Range. Exception e) { Console. Write. Line(e. Message); } catch (Exception e) { Console. Write. Line(e. Message); } finally { my. Car. Crank. Tunes(false); } 61

Corrupted State Exceptions (. NET 4. 0) …czyli tam, gdzie zaczynają się prawdziwe problemy Corrupted State Exceptions (. NET 4. 0) …czyli tam, gdzie zaczynają się prawdziwe problemy a gdzie słońce już nie dochodzi. System. Runtime. Exception. Services ->. NET 4. 0 SDK manual class Program { //bez tego CSE nie zostanie wyłapane: [Handled. Process. Corrupted. State. Exceptions] static int Main(string[] args) { try { //poniższa metoda uruchamia główny program: Run. My. Application(); } catch (Exception ex) { //ten kod niewiele naprawia, ale przynajmniej mówi, na co umarł: Console. Write. Line("Bring out your dead!!! : {0}", ex. Message); return -1; //nawet DOS to zrozumie – etykieta %ERROR% } return 0; //normal program termination } } 62

Część VIII: Czas życia obiektów 63 Część VIII: Czas życia obiektów 63

Garbage Collector Tworzenie obiektów – przez działanie CLR Brak słowa ‘delete’, można przypisać null Garbage Collector Tworzenie obiektów – przez działanie CLR Brak słowa ‘delete’, można przypisać null referencji, ale… (c. d. ) GC: podział obiektów na generacje 0 – 2, w zależności od tego, jak długo już są w pamięci. W. NET 4. 0 trochę inaczej działa GC niż w 1. 0 – 3. 5, optymalizacja czyszczenia generacji 0 i generacji 1 64

Metody z System. Gc Add. Memory. Pressure() ◦ Remove. Memory. Pressure() Collection. Count() Get. Metody z System. Gc Add. Memory. Pressure() ◦ Remove. Memory. Pressure() Collection. Count() Get. Generation() Get. Total. Memory() Max. Generation() Suppress. Finaliza() Wait. For. Pending. Finalizers() e. g. : ◦ GC. Get. Generation(ref. To. Object)); 65

Garbage Collector (seq. ) GC. Collect(); //razem z: GC. Wait. For. Pending. Finalizers(); public Garbage Collector (seq. ) GC. Collect(); //razem z: GC. Wait. For. Pending. Finalizers(); public enum GCCollection. Mode{ Default, //Forced, //collect it now Optimized //decide when } protected virtual void Finalize() // w System. Object class Klasa { protected override void Finalize() { } //compile-time error ~Klasa() { //destruktor (C++) } } 66

Interfejs IDisposable public interface IDisposable { void Dispose(); } Przykład: class Jakas. Klasa : Interfejs IDisposable public interface IDisposable { void Dispose(); } Przykład: class Jakas. Klasa : IDisposable { public void Dispose() { //clean } } Wywołanie: static void Main(string[] args) { Jakas. Klasa obiekt = new Jakas. Klasa(); if (obiekt is IDisposable) { obiekt. Dispose(); } } 67

Rozkaz using Jakas. Klasa rw = new Jakas. Klasa(); try {. . . } Rozkaz using Jakas. Klasa rw = new Jakas. Klasa(); try {. . . } finally { rw. Dispose(); } I tak dla każdego obiektu? … zgroza. Lepiej: static void Main(string[] args) { // Dispose() is called automatically using (Jakas. Klasa rw = new Jakas. Klasa()) { //. . . } } 68

Finalize + Dispose (a raczej LUB) class Jakas. Klasa : IDisposable { ~Jakas. Klasa() Finalize + Dispose (a raczej LUB) class Jakas. Klasa : IDisposable { ~Jakas. Klasa() { //czyści i dezynfekuje //nie wywoływać Dispose() po tym } public void Dispose() { //nie wywoływać Finalize po tej metodzie //(bo po co? ), a więc: GC. Suppress. Finalize(this); } } 69

A najlepiej tak: class Klasa : IDisposable { private bool disposed = false; public A najlepiej tak: class Klasa : IDisposable { private bool disposed = false; public void Dispose() { Clean. Up(true); GC. Suppress. Finalize(this); } private void Clean. Up(bool disposing) { if (this. disposed == false) { if (disposing) { // Czyszczenie obiektów z pamięci } // Resztę czyścić tutaj } disposed = true; } ~Klasa() { Clean. Up(false); } } 70

Rise!!! (and eat brains) public class Base. Obj { protected override void Finalize() { Rise!!! (and eat brains) public class Base. Obj { protected override void Finalize() { Application. Obj. Holder = this; } } class Application { static public Object Obj. Holder; // Defaults to null } Powyższa metoda WSKRZESZA obiekt. Z tym, że może nam wyjść zombie – jeśli jego podobiekty już naprawdę-naprawdę nie istnieją, a nasz ożywieniec się do nich odwoła – Exception mamy jak w banku (cypryjskim). 71

Sztuka nieśmiertelności c. d. public class Base. Obj { protected override void Finalize() { Sztuka nieśmiertelności c. d. public class Base. Obj { protected override void Finalize() { Application. Obj. Holder = this; GC. Register. For. Finalize(this); } } Ten obiekt jest nieśmiertelny. Implikacje programistyczne mogą być takie same jak społeczne – totalny bajzel, o ile nie będziemy bardzo ostrożni. 72

<Lazy> class (. NET 4. 0) Stwórz obiekt, ale w sumie, to go nie class (. NET 4. 0) Stwórz obiekt, ale w sumie, to go nie twórz. Przynajmniej nie do czasu, aż cokolwiek będzie chciało go użyć: private Lazy moj. Obiekt = new Lazy(); Poniższe: private Lazy moj. Obiekt = new Lazy( () => { return new Klasa(); } ); zawiera wyrażenie Lamba, do obsługi delegata (typu, a jakże: generycznego), który umożliwia zdefiniowanie, którym konstruktorem obiekt ma być utworzony. Pytania? 73

Część: IX: Interfejsy 74 Część: IX: Interfejsy 74

Przykład class Program { static void Main(string[] args) { // wszystkie 3 klasy obiektów Przykład class Program { static void Main(string[] args) { // wszystkie 3 klasy obiektów dziedziczą z interfejsu IClonable: string my. Str = "Hello"; Operating. System unix. OS = new Operating. System(Platform. ID. Unix, new Version()); System. Data. Sql. Client. Sql. Connection sql. Cnn = new System. Data. Sql. Client. Sql. Connection(); // więc ich trzy obiekty mogą być posłane w te samą metodę: Clone. Me(my. Str); Clone. Me(unix. OS); Clone. Me(sql. Cnn); Console. Read. Line(); } private static void Clone. Me(ICloneable c) { object the. Clone = c. Clone(); Console. Write. Line("Klon: {0}", the. Clone. Get. Type(). Name); } } 75

W interfejsie: żadnych pól ◦ mogą prototypy właściwości (properties), czyli tylko: int Punkt { W interfejsie: żadnych pól ◦ mogą prototypy właściwości (properties), czyli tylko: int Punkt { get; set; } żadnych konstruktorów- żadnych implementacji metod wszystkie domyślnie public abstract nie dziedziczą z bazowych ukrytych, choć mogą jawnie z innych bazowych interfejsów Interfejsy definiują pewne wspólne funkcjonalności, które wszystkie klasy dziedziczące muszą implementować. 76

Dziedziczenie, weryfikacja dziedziczenia z jednego interfejsu z wielu interfejsów z klasy bazowej i interfejsu(ów) Dziedziczenie, weryfikacja dziedziczenia z jednego interfejsu z wielu interfejsów z klasy bazowej i interfejsu(ów) static void Main(string[] args) { Kolo c = new Kolo(); IPunkt itf. Pt = null; try { itf. Pt = (IPunkt)c; Console. Write. Line(itf. Pt. Points); } catch (Invalid. Cast. Exception e) { Console. Write. Line(e. Message); } Console. Read. Line(); } 77

as / is ponownie Kolo kolko = new Kolo(); IPointy inter = kolko as as / is ponownie Kolo kolko = new Kolo(); IPointy inter = kolko as IPointy; if (kolko != null){. . . } else {. . . } lub: Kolo kolko = new Kolo(); if (kolko is IPointy){. . . } else {. . . } 78

Zastosowania interface – parametry wejściowe metody interface – zwracany przez metodę tablica interfejsów – Zastosowania interface – parametry wejściowe metody interface – zwracany przez metodę tablica interfejsów – tj. (jak wyżej z resztą) obiektów klas implementujących danych (wspólny) interfejs implementacja w VS 2010: zwykła i jawna (wymuszona) hierarchia interfejsów: dziedziczenie ‘funkcjonalności’ metod abstrakcyjnych interfejsów nadrzędnych 79

Interfejsy IEnumerable / IEnumerator IEnumerable: public interface IEnumerable { IEnumerator Get. Enumerator(); } IEnumerator: Interfejsy IEnumerable / IEnumerator IEnumerable: public interface IEnumerable { IEnumerator Get. Enumerator(); } IEnumerator: public interface IEnumerator { bool Move. Next (); // następna pozycja ‘kursora’ object Current { get; } // pobierz element z kursora void Reset (); // kursor na pierwszą pozycję } Magic word: yield 80

IClonable public interface ICloneable { object Clone(); } Od programisty zależy, czy to będzie IClonable public interface ICloneable { object Clone(); } Od programisty zależy, czy to będzie prawdziwa, głęboka kopia (deep-copy, innymi słowy wszystko, łącznie z obiektami potomnymi), czy tylko płytka (shallow-copy) 81

IComparable (np. dla funkcji Sort() ) public interface IComparable { int Compare. To(object o); IComparable (np. dla funkcji Sort() ) public interface IComparable { int Compare. To(object o); } Na przykład: int IComparable. Compare. To(object obj) { Car temp = obj as Car; if (temp != null) { if (this. Car. ID > temp. Car. ID) return 1; //cokolwiek >0 – obiekt po aktualnym if (this. Car. ID < temp. Car. ID) return -1; //cokolwiek mniej niż zero: obiekt przed aktualnym else return 0; //te same obiekty } else throw new Argument. Exception("!!!!"); } 82

IComparer interface IComparer { int Compare(object o 1, object o 2); } na przykład: IComparer interface IComparer { int Compare(object o 1, object o 2); } na przykład: int IComparer. Compare(object o 1, object o 2) { Car t 1 = o 1 as Car; Car t 2 = o 2 as Car; if (t 1 != null && t 2 != null) return String. Compare(t 1. name, t 2. name); else throw new Argument. Exception("!!!"); } zwracanie jako własciwość: public static IComparer Sort. By. Pet. Name { get { return (IComparer)new Pet. Name. Comparer(); } } 83

Część X: Kolekcje, typy generyczne 84 Część X: Kolekcje, typy generyczne 84

System. Collections (non-generic) Array. List (: IList, ICollection, IEnumerable, IClonable) Hashtable (: IDictionary, ICollection, System. Collections (non-generic) Array. List (: IList, ICollection, IEnumerable, IClonable) Hashtable (: IDictionary, ICollection, IEnumerable, IClonable) Queue (FIFO) (: ICollection, IEnumerable, IClonable) Sorted. List (: IDictionary, ICollection, IEnumerable, IClonable) Stack (LIFO) (: ICollection, IEnumerable, IClonable) 85

Wady wolniejsze niż nowe, typu generic; niezbyt bezpieczne, przechowują System. Object, więc za każdym Wady wolniejsze niż nowe, typu generic; niezbyt bezpieczne, przechowują System. Object, więc za każdym razem trzeba się martwić, czy to co wyciągamy z kolekcji na pewno jest odpowiedniego typu; już od. NET 2. 0 weszły kolekcje generyczne, więc warto się w końcu przestawić; Konkluzja: omijać szeroki łukiem, używać System. Collections. Generic (to samo, tylko „lepiej, szybciej, taniej”) 86

Przykład stosowania <generic> static void Use. Generic() { List<Person> more. People = new List<Person>(); Przykład stosowania static void Use. Generic() { List more. People = new List(); more. People. Add(new Person("Jan", "Nowak", 30)); Console. Write. Line(more. People[0]); List more. Ints = new List(); more. Ints. Add(1); more. Ints. Add(2); int sum = more. Ints[0] + more. Ints[1]; // Compile-time error: // more. Ints. Add(new Person()); } 87

Interfejsy kolekcji z pakietu System. Collections. Generic ICollection<T> IComparer<T> IDictionary<TKey, TValue> IEnumerable<T> IEnumerator<T> IList Interfejsy kolekcji z pakietu System. Collections. Generic ICollection IComparer IDictionary IEnumerable IEnumerator IList ISet 88

Klasy System. Collections. Generic Dictionary<TKey, TValue> List<T> Linked. List<T> Queue<T> Sorted. Dictionary<TKey, TValue> Sorted. Klasy System. Collections. Generic Dictionary List Linked. List Queue Sorted. Dictionary Sorted. Set Stack ◦ pakiet System. Core: Hast. Set 89

Inicjalizacja obiektów: int[] my. Array. Of. Ints = { 0, 1, 2, 3, 4, Inicjalizacja obiektów: int[] my. Array. Of. Ints = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; List my. Generic. List = new List { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; Array. List my. List = new Array. List { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; List my. List. Of. Points = new List { new Point { X = 2, Y = 2 }, new Point { X = 3, Y = 3 }, new Point(Point. Color. Blood. Red){ X = 4, Y = 4 } }; 90

List<T> List<Person> people = new List<Person>() { new Person {First. Name= List List people = new List() { new Person {First. Name= "Homer", Last. Name="Simpson", Age=47}, new Person {First. Name= "Marge", Last. Name="Simpson", Age=45}, new Person {First. Name= "Lisa", Last. Name="Simpson", Age=9}, new Person {First. Name= "Bart", Last. Name="Simpson", Age=8} }; Console. Write. Line("Items in list: {0}", people. Count); foreach (Person p in people) Console. Write. Line(p); Console. Write. Line("n->Inserting new person. "); people. Insert(2, new Person { First. Name = "Maggie", Last. Name = "Simpson", Age = 2 }); Console. Write. Line("Items in list: {0}", people. Count); Person[] array. Of. People = people. To. Array(); for (int i = 0; i < array. Of. People. Length; i++) { Console. Write. Line("First Names: {0}", array. Of. People[i]. First. Name); } 91

List<T> wynik Items in list: 4 Name: Homer Simpson, Age: 47 Name: Marge Simpson, List wynik Items in list: 4 Name: Homer Simpson, Age: 47 Name: Marge Simpson, Age: 45 Name: Lisa Simpson, Age: 9 Name: Bart Simpson, Age: 8 ->Inserting new person. Items in list: 5 First Names: Homer First Names: Marge First Names: Maggie First Names: Lisa First Names: Bart 92

Stack<T> Stack<Person> stack. Of. People = stack. Of. People. Push(new Person = 47 }); Stack Stack stack. Of. People = stack. Of. People. Push(new Person = 47 }); stack. Of. People. Push(new Person = 45 }); stack. Of. People. Push(new Person 9 }); new Stack(); { First. Name = "Homer", Last. Name = "Simpson", Age { First. Name = "Marge", Last. Name = "Simpson", Age { First. Name = "Lisa", Last. Name = "Simpson", Age = Console. Write. Line("First person is: {0}", stack. Of. People. Peek()); Console. Write. Line("Popped off {0}", stack. Of. People. Pop()); Console. Write. Line("n. First person item is: {0}", stack. Of. People. Peek()); Console. Write. Line("Popped off {0}", stack. Of. People. Pop()); try { Console. Write. Line("nn. First person is: {0}", stack. Of. People. Peek()); Console. Write. Line("Popped off {0}", stack. Of. People. Pop()); } catch (Invalid. Operation. Exception ex) { Console. Write. Line("n. Error! {0}", ex. Message); } 93

Stack<T> wynik First person is: Name: Lisa Simpson, Age: 9 Popped off Name: Lisa Stack wynik First person is: Name: Lisa Simpson, Age: 9 Popped off Name: Lisa Simpson, Age: 9 First person is: Name: Marge Simpson, Age: 45 Popped off Name: Marge Simpson, Age: 45 First person item is: Name: Homer Simpson, Age: 47 Popped off Name: Homer Simpson, Age: 47 Error! Stack empty. 94

Queue<T> Queue<Person> people. Q = new Queue<Person>(); people. Q. Enqueue(new Person { First. Name Queue Queue people. Q = new Queue(); people. Q. Enqueue(new Person { First. Name = "Homer", Last. Name = "Simpson", Age = 47 }); people. Q. Enqueue(new Person { First. Name = "Marge", Last. Name = "Simpson", Age = 45 }); people. Q. Enqueue(new Person { First. Name = "Lisa", Last. Name = "Simpson", Age = 9 }); Console. Write. Line("{0} is first in line!", people. Q. Peek(). First. Name); Get. Coffee(people. Q. Dequeue()); try{ Get. Coffee(people. Q. Dequeue()); } catch (Invalid. Operation. Exception e) { Console. Write. Line("Error! {0}", e. Message); } 95

Queue<T> wynik Homer is first in line! Homer got coffee! Marge got coffee! Lisa Queue wynik Homer is first in line! Homer got coffee! Marge got coffee! Lisa got coffee! Error! Queue empty. 96

Sorted. Set<T> class Sort. People. By. Age : IComparer<Person> { public int Compare(Person first. Sorted. Set class Sort. People. By. Age : IComparer { public int Compare(Person first. Person, Person second. Person) { if (first. Person. Age > second. Person. Age) return 1; if (first. Person. Age < second. Person. Age) return -1; else return 0; } } private static void Use. Sorted. Set() { Sorted. Set set. Of. People = new Sorted. Set(new Sort. People. By. Age ()) { new Person {First. Name= "Homer", Last. Name="Simpson", Age=47}, new Person {First. Name= "Marge", Last. Name="Simpson", Age=45}, new Person {First. Name= "Lisa", Last. Name="Simpson", Age=9}, new Person {First. Name= "Bart", Last. Name="Simpson", Age=8} }; foreach (Person p in set. Of. People) { Console. Write. Line(p); } Console. Write. Line(); set. Of. People. Add(new Person { First. Name = "Saku", Last. Name = "Jones", Age = 1 }); set. Of. People. Add(new Person { First. Name = "Mikko", Last. Name = "Jones", Age = 32 }); foreach (Person p in set. Of. People) { Console. Write. Line(p); } } 97

Sorted. Set<T> wynik Name: Bart Simpson, Age: 8 Name: Lisa Simpson, Age: 9 Name: Sorted. Set wynik Name: Bart Simpson, Age: 8 Name: Lisa Simpson, Age: 9 Name: Marge Simpson, Age: 45 Name: Homer Simpson, Age: 47 Name: Saku Jones, Age: 1 Name: Bart Simpson, Age: 8 Name: Lisa Simpson, Age: 9 Name: Mikko Jones, Age: 32 Name: Marge Simpson, Age: 45 Name: Homer Simpson, Age: 47 98

Tworzenie swoich własnych <generic> np. dla podmiany ze sobą referencji obiektów/struktur DOWOLNEGO typu: static Tworzenie swoich własnych np. dla podmiany ze sobą referencji obiektów/struktur DOWOLNEGO typu: static void Swap(ref T a, ref T b) { T temp; temp = a; a = b; b = temp; } static void Display. Base. Class() { Console. Write. Line("Base class of {0}: {1}. ", typeof(T). Base. Type); } Wywołanie: bool b 1 = true, b 2 = false; Swap(ref b 1, ref b 2); Lepiej jednak tak (większa jaśność dla innych): Swap(ref b 1, ref b 2); 99

Część XI: Delegates, events, Lambda expressions 100 Część XI: Delegates, events, Lambda expressions 100

Garść teorii Do tego miejsca metody coś robiły po tym, jak się je kopnęło, Garść teorii Do tego miejsca metody coś robiły po tym, jak się je kopnęło, w ten czy inny sposób. Idea delegatów i zdarzeń jest taka, żeby metody mogły reagować zwrotnie, tj. same powodować pewne zachowania całego programu, jeśli zaistnieją pewne warunki (dajmy na to: startowe). Delegat to obiekt, który przechowuje informacje o: ◦ metodach, do których ma się odwołać w razie konieczności ◦ ich parametrach wejściowych (typy) ◦ ich paramterach wyjściowych (typy) 101

public delegate string My. Delegate(bool a, bool b, bool c); Zmienia się w: sealed public delegate string My. Delegate(bool a, bool b, bool c); Zmienia się w: sealed class My. Delegate : System. Multicast. Delegate { public string Invoke(bool a, bool b, bool c); public IAsync. Result Begin. Invoke(bool a, bool b, bool c, Async. Callback cb, object state); public string End. Invoke(IAsync. Result result); } 102

Przykład: public delegate int Binary. Op(int x, int y); public class Simple. Math { Przykład: public delegate int Binary. Op(int x, int y); public class Simple. Math { public static int Add(int x, int y) { return x + y; } public static int Subtract(int x, int y) { return x - y; } } class Program { static void Main(string[] args) { Binary. Op b = new Binary. Op(Simple. Math. Add); Console. Write. Line("10 + 10 is {0}", b(10, 10)); Console. Read. Line(); } } 103

 lista parametrów delagata oraz metod, które zawiera musi się zgadzać i to dokładnie lista parametrów delagata oraz metod, które zawiera musi się zgadzać i to dokładnie wyświetlanie zawartości: static void Display. Delegate. Info(Delegate del. Obj) { foreach (Delegate d in del. Obj. Get. Invocation. List()) { Console. Write. Line("Method Name: {0}", d. Method); Console. Write. Line("Type Name: {0}", d. Target); } } 104

 Dodawania i odejmowanie metod do delegata poprzez np. operatory += oraz -= ; Dodawania i odejmowanie metod do delegata poprzez np. operatory += oraz -= ; konstrukcja delegatów wspiera generyczność: po ludzku, możliwa konstrukcja jak np. : public delegate void My. Generic. Delegate(T arg); 105

Events { public delegate void Car. Engine. Handler(string msg); public event Car. Engine. Handler Events { public delegate void Car. Engine. Handler(string msg); public event Car. Engine. Handler Exploded; public event Car. Engine. Handler About. To. Blow; } Najpierw należy określić delegata, który będzie przetrzymywać metody, które należy wywołać. Następnie określamy zdarzenia (events), które zamierzamy odpalić (z parametrami zdefiniowanymi jak w delegacie, czyli np. > Exploded("wybuchłem…”); ) Po odpaleniu eventu, odpalany jest delegat, który wykonuje metody, które ma w sobie zawarte, z parametrami jakie dostał event (dlatego musi być zgodność między nimi). 106

Część XII: Indeksery, przeładowanie operatorów 107 Część XII: Indeksery, przeładowanie operatorów 107

Indeksery, przykład People. Collection my. People = new People. Collection(); my. People[0] = new Indeksery, przykład People. Collection my. People = new People. Collection(); my. People[0] = new Person("Homer", "Simpson", 40); my. People[1] = new Person("Marge", "Simpson", 38); my. People[2] = new Person("Lisa", "Simpson", 9); my. People[3] = new Person("Bart", "Simpson", 7); my. People[4] = new Person("Maggie", "Simpson", 2); for (int i = 0; i < my. People. Count; i++) { Console. Write. Line("Person number: {0}", i); Console. Write. Line("Name: {0} {1}", my. People[i]. First. Name, my. People[i]. Last. Name); Console. Write. Line("Age: {0}", my. People[i]. Age); Console. Write. Line(); } 108

Przykład, c. d. Jak zdefiniować indekser dla poprzedniego przykładu? public class People. Collection : Przykład, c. d. Jak zdefiniować indekser dla poprzedniego przykładu? public class People. Collection : IEnumerable { private Array. List ar. People = new Array. List(); public Person this[int index] { get { return (Person)ar. People[index]; } set { ar. People. Insert(index, value); } } } 109

Indeksowanie po typie string public class People. Collection : IEnumerable { private Dictionary<string, Person> Indeksowanie po typie string public class People. Collection : IEnumerable { private Dictionary list. People = new Dictionary(); public Person this[string name] { get { return (Person)list. People[name]; } set { list. People[name] = value; } } IEnumerator IEnumerable. Get. Enumerator() { return list. People. Get. Enumerator(); } } czyli w ten sposób: Person homer = my. People["Homer"]; Console. Write. Line(homer. To. String()); 110

 indeksery mogą być przeładowane, tj. kilka różnych dla tego samego obiektu, np. ideksowanie indeksery mogą być przeładowane, tj. kilka różnych dla tego samego obiektu, np. ideksowanie zarówno po liczbach porządkowych jak i po string mogą być używane wielowymiarowo: public class Some. Container { private int[ , ] my 2 Dint. Array = new int[10, 10]; public int this[int row, int column] { /* get / set odpowiednio skonstruowane */ } } indeksery mogą być definiowane w interfejsach, aby klasy dziedziczące implementowały odpowiednie metody indeksujące 111

Przeciążenie operatorów Przykład: public static Point operator +(Point p 1, Point p 2) { Przeciążenie operatorów Przykład: public static Point operator +(Point p 1, Point p 2) { return new Point(p 1. X + p 2. X, p 1. Y + p 2. Y); } Zawsze public, zawsze static (i trzeba to wprost wpisywać w kodzie) Kolejność parametrów jest ważna przy wywoływaniu (o ile są różnych typów) Możliwe dla operatorów unarnych (e. g. +, -, ~, !, ++, --), binarnych (+, -, *, /, itd. ) i innych Operatory = i != ; < i >; <= i => MUSZĄ być przeładowane razem w kodzie (i jeden, i drugi). Niemożliwe dla [], () oraz operatorów skróconych, tj. np. -=, +=, *=, itd. 112

Część XIII: Wielowątkowość 113 Część XIII: Wielowątkowość 113

And now… the delegates (again) Delegaty mogą wywoływać metody asynchronicznie Załóżmy, że mamy delegata: And now… the delegates (again) Delegaty mogą wywoływać metody asynchronicznie Załóżmy, że mamy delegata: public delegate int Binary. Op(int x, int y); Dla niego tworzony jest (niejawnie) obiekt klasy: public sealed class Binary. Op : System. Multicast. Delegate { public Binary. Op(object target, uint function. Address); public void Invoke(int x, int y); public IAsync. Result Begin. Invoke(int x, int y, Async. Callback cb, object state); public int End. Invoke(IAsync. Result result); } 114

Delegaci, asynchroniczność, c. d. Gdy delegat z przykładu zostanie aktywowany, metoda Invoke wykona się Delegaci, asynchroniczność, c. d. Gdy delegat z przykładu zostanie aktywowany, metoda Invoke wykona się synchronicznie, tj. główny wątek aplikacji zostanie zatrzymany do czasu, aż wszystko co delegat miał wykonać, zostanie wykonane. Na przykład (dalszy slajd) w momencie aktywacji delegata zawierającego metodę, która między innymi wstrzymuje główny wątek aplikacji, wszystkie kolejne polecenia kodu muszą czekać, aż delegat skończy pracować. 115

Na początek: synchronicznie static void Main(string[] args) { Console. Write. Line( Na początek: synchronicznie static void Main(string[] args) { Console. Write. Line("***** Synch Delegate Review *****" ); Console. Write. Line("Main() invoked on thread {0}. ", Thread. Current. Thread. Managed. Thread. Id); Binary. Op b = new Binary. Op(Add); // Could also write b. Invoke(10, 10): int answer = b(10, 10); Console. Write. Line("Doing more work in Main()!"); Console. Write. Line("10 + 10 is {0}. ", answer); Console. Read. Line(); } static int Add(int x, int y) { Console. Write. Line("Add() invoked on thread {0}. ", Thread. Current. Thread. Managed. Thread. Id); Thread. Sleep(5000); return x + y; } 116

No więc co z tą asynchronicznością? ? Delegat z przykładu (każdy w zasadzie) ma No więc co z tą asynchronicznością? ? Delegat z przykładu (każdy w zasadzie) ma automatycznie wygenerowane 2 tajemnicze metody: public IAsync. Result Begin. Invoke(int x, int y, Async. Callback cb, object state); public int End. Invoke(IAsync. Result result); Gdzie IAsync. Result to interfejs, dzięki któremu zarządza się wynikiem (a dokładnie oczekiwaniem nań): public interface IAsync. Result { object Async. State { get; } Wait. Handle Async. Wait. Handle { get; } bool Completed. Synchronously { get; } bool Is. Completed { get; } } 117

Najłatwiej tak: static void Main(string[] args) { Console. Write. Line( Najłatwiej tak: static void Main(string[] args) { Console. Write. Line("***** Async Delegate Invocation *****" ); Console. Write. Line("Main() invoked on thread {0}. ", Thread. Current. Thread. Managed. Thread. Id); // Invoke Add() on a secondary thread. Binary. Op b = new Binary. Op(Add); IAsync. Result ift. AR = b. Begin. Invoke(10, null, null); Console. Write. Line("Doing more work in Main()!"); int answer = b. End. Invoke(ift. AR); Console. Write. Line("10 + 10 is {0}. ", answer); Console. Read. Line(); } Linia int answer = b. End. Invoke(ift. AR); odpowiada za to, żeby nie kazać głównemu wątkowi wyświetlić wyniku, jeśli go jeszcze nie ma (w przykładzie to raczej nie jest trudne, ale jeśli np. w delegacie będzie zadanie ściągnięcia pół giga kontrabandy z internetu, to już może trochę potrwać…) 118

Jak stwierdzić, czy delegat skończył? Problem oczywiście jest taki, że wciąż program może w Jak stwierdzić, czy delegat skończył? Problem oczywiście jest taki, że wciąż program może w przykładzie marnować czas, jeśli między wywołaniem delegata a oczekiwaniem na wynik (End. Invoke) zadania skończą się wcześnie, tak więc można użyć: Binary. Op b = new Binary. Op(Add); IAsync. Result ift. AR = b. Begin. Invoke(10, null, null); while(!ift. AR. Is. Completed) { Console. Write. Line("Doing more work in Main()!"); Thread. Sleep(1000); } int answer = b. End. Invoke(ift. AR); 119

Oddzwonimy do pana, jak skończymy… Jeszcze inaczej: while (!ift. AR. Async. Wait. Handle. Wait. Oddzwonimy do pana, jak skończymy… Jeszcze inaczej: while (!ift. AR. Async. Wait. Handle. Wait. One(1000, true)) { Console. Write. Line("Doing more work in Main()!"); } Jeszcze inteligentniej (=jeszcze trudniej) – a może by tak oprócz wątku głównego aplikacji (1), w trakcie pracy którego asynchronicznie robi coś delegat w wątku (2), zaprząc do pracy TRZECI wątek (3), który będzie sprawdzać co robi (2), i jak stwierdzi, że (2) skończył, da informację (1), że ma jakieś wyniki do obsłużenia ? Można oczywiście: 120

public delegate int Binary. Op(int x, int y); class Program { private static bool public delegate int Binary. Op(int x, int y); class Program { private static bool is. Done = false; static void Main(string[] args) { Binary. Op b = new Binary. Op(Add); IAsync. Result ift. AR = b. Begin. Invoke(10, new Async. Callback(Add. Complete), null); while (!is. Done) { Thread. Sleep(1000); Console. Write. Line("Working. . "); } Console. Read. Line(); static int Add(int x, int y) { Thread. Sleep(5000); return x + y; } static void Add. Complete(IAsync. Result itf. AR) { Console. Write. Line("Your addition is complete"); is. Done = true; } } 121

C. d. Poprzedni obiekt KLASY Async. Callback nie miał dostępu do delagata, który miał C. d. Poprzedni obiekt KLASY Async. Callback nie miał dostępu do delagata, który miał monitorować – robił tylko za posłańca z wiadomością, że monitorowany obiekt skończył. Aby uzyskać dostęp do monitorowanego delagata (i jego wyników) należy użyć takiej metody Add. Complete() dla poprzedniego przykładu: static void Add. Complete(IAsync. Result itf. AR) { Async. Result ar = (Async. Result)itf. AR; //rzutowanie Binary. Op b = (Binary. Op)ar. Async. Delegate; Console. Write. Line("10 + 10 is {0}. ", b. End. Invoke(itf. AR)); is. Done = true; } 122

Stan obiektu IAsync. Result ift. AR = b. Begin. Invoke(10, new Async. Callback(Add. Complete), Stan obiektu IAsync. Result ift. AR = b. Begin. Invoke(10, new Async. Callback(Add. Complete), null); mamy ostatni tajemniczy null pod koniec. Definicja metody to: public IAsync. Result Begin. Invoke(int x, int y, Async. Callback cb, object state); tak więc chodzi o stan monitorowanego procesu. Dla przykładu, jeśli wywołanie delegata to: IAsync. Result ift. AR = b. Begin. Invoke(10, new Async. Callback(Add. Complete), "Dzięki za dodanie tych dwóch liczb"); Wtedy możemy to odtworzyć poprzez: static void Add. Complete(IAsync. Result itf. AR) {. . . string msg = (string)itf. AR. Async. State; Console. Write. Line(msg); } is. Done = true; 123

Prawdziwa wielowątkowość: System. Threading Przykład kilku właściwości obiektu z Thread: static void Main(string[] args) Prawdziwa wielowątkowość: System. Threading Przykład kilku właściwości obiektu z Thread: static void Main(string[] args) { Thread primary. Thread = Thread. Current. Thread; primary. Thread. Name = "The. Primary. Thread"; //!!!! Przydatne do debugowania Console. Write. Line("Name of current App. Domain: {0}", Thread. Get. Domain(). Friendly. Name); Console. Write. Line("ID of current Context: {0}", Thread. Current. Context. ID); Console. Write. Line("Thread Name: {0}", primary. Thread. Name); Console. Write. Line("Has thread started? : {0}", primary. Thread. Is. Alive); Console. Write. Line("Priority Level: {0}", primary. Thread. Priority); Console. Write. Line("Thread State: {0}", primary. Thread. State); Console. Read. Line(); } Wynik: Name of current App. Domain: Thread. Stats. exe ID of current Context: 0 Thread Name: The. Primary. Thread Has thread started? : True Priority Level: Normal // enum Thread. Priority – nie jest to obligatoryjne dla środowiska Thread State: Running 124

Przykład (1) Mamy drukarkę, która coś tam… drukuje (niespodzianka): public class Printer { public Przykład (1) Mamy drukarkę, która coś tam… drukuje (niespodzianka): public class Printer { public void Print. Numbers() { Console. Write. Line("-> {0} is executing Print. Numbers()", Thread. Current. Thread. Name); Console. Write("Your numbers: "); for (int i = 0; i < 10; i++) { Console. Write("{0}, ", i); Thread. Sleep(2000); } Console. Write. Line(); } } 125

Główny kod: static void Main(string[] args) { Printer p = new Printer(); Thread background. Główny kod: static void Main(string[] args) { Printer p = new Printer(); Thread background. Thread = new Thread(new Thread. Start(p. Print. Numbers)); background. Thread. Name = "Secondary"; background. Thread. Start(); } Po ostatnim poleceniu całość działań obiektu drukarki będzie realizowana w osobnym wątku, więc jeśli będą dalsze polecenia po background. Thread. Start(), to spokojnie się zrealizują. Ważna jest liczba rdzeni CPU! Na jednoprocesorowym komputerze program będzie bardziej „responsywny”, ale na pewno nie szybszy! 126

c. d. Thread. Start() może przyjmować tylko metody zwracające void i nie przejmujące żadnych c. d. Thread. Start() może przyjmować tylko metody zwracające void i nie przejmujące żadnych argumentów – czyli tak trochę biednie. Przykład: class Add. Params { public int a, b; public Add. Params(int numb 1, int numb 2) { a = numb 1; b = numb 2; } } Oraz metoda statyczna: static void Add(object data) { if (data is Add. Params) { Add. Params ap = (Add. Params)data; Console. Write. Line("{0} + {1} is {2}", ap. a, ap. b, ap. a + ap. b); } } 127

Realizacja wątku z poprzedniego slajdu: Add. Params ap = new Add. Params(10, 10); Thread Realizacja wątku z poprzedniego slajdu: Add. Params ap = new Add. Params(10, 10); Thread t = new Thread(new Parameterized. Thread. Start(Add)); t. Start(ap); // Force a wait to let other thread finish. Thread. Sleep(5); Console. Read. Line(); 128

Wątki pierwszo i drugoplanowe Wątki pierwszoplanowe muszą zostać (wszystkie) zakończone, aby środowisko. NET wyładowało Wątki pierwszo i drugoplanowe Wątki pierwszoplanowe muszą zostać (wszystkie) zakończone, aby środowisko. NET wyładowało z pamięci aplikację (np. metoda Main – dopóki jej ostatnia linia się nie wykona, aplikacja działa). Wątki drugoplanowe (czasem zwane demonami (linux? )) są kończone, jeżeli zakończył się ostatni wątek pierwszoplanowy. Na przykład: jeśli poprzez polecenie: jakiśWątek. Is. Background = true; ustawiamy drugoplanowość „jakiegośWątku”, to niezależnie, czy zakończył on już swoje zadanie czy nie(!), zostanie wyładowany z systemu przez środowisko. NET, jeżeli ostatni wątek pierwszoplanowy został właśnie zakończony. 129

Synchronizacja, czyli wszyscy na raz, a każdy co innego… public void Print. Numbers() { Synchronizacja, czyli wszyscy na raz, a każdy co innego… public void Print. Numbers() { lock (thread. Lock) { Console. Write("Your numbers: "); for (int i = 0; i < 10; i++) { Random r = new Random(); Thread. Sleep(1000 * r. Next(5)); Console. Write("{0}, ", i); } Console. Write. Line(); } } Załóżmy, że gdzieś w kodzie mamy private object thread. Lock = new Object(); służący jako token blokady, to wszystko wewnątrz kodu lock{ …} będzie wykonywane na raz dla jednego wątku. 130

c. d. Inaczej: jeśli poprzedni kod nie zawierałby klauzuli lock(coś) { … }, lecz c. d. Inaczej: jeśli poprzedni kod nie zawierałby klauzuli lock(coś) { … }, lecz tylko te polecenia co drukują liczby, wtedy, jeśli stworzylibyśmy np. 10, 20 czy 100 takich wątków i uruchomili wszystkie równocześnie, to każdy w swoim czasie coś by tam drukował, jednocześnie na tej samej konsoli. Czyli wyświetlane liczby od 1 do 10 szybko by się wymieszały na ekranie. Jeśli mamy klauzulę lock z jakimś obiektem robiącym za token, to nawet jeśli mamy 100 takich samych wątków, wtedy pierwszy, który natrafia na lock realizuje go DO KOŃCA po czym dopiero wtedy wątek drugi, trzeci i kolejne w ten sam sposób będą wykonywane. Jeszcze innymi słowy nadal są to wątki pracujące w tle, ale przynajmniej nie jeden przez drugiego, tylko w kolejności (ale ta kolejność dotyczy tylko realizacji poleceń wewnątrz lock(token) { … } ! 131

Lock = System. Threading. Monitor Poprzedni kod, a raczej klazula lock jest niejawnie zamienia Lock = System. Threading. Monitor Poprzedni kod, a raczej klazula lock jest niejawnie zamienia na: public void Print. Numbers() { Monitor. Enter(thread. Lock); try { … } finally { Monitor. Exit(thread. Lock); } } Lock(){} jest szybsze do zapisania, ale użycie Monitora daje dostęp do większej liczby metod, np. nakazujących czekać głównemu wątkowi, czy informujących wątki poboczne, że coś się dzieje, np. aktualny kończy pracę. 132

Inne formy synchronizacji System. Threading. Interlocked – dla pewnych atomowych poleceń, jak inkremencja czy Inne formy synchronizacji System. Threading. Interlocked – dla pewnych atomowych poleceń, jak inkremencja czy dekrementacja zmiennej o 1, bezpieczne porównanie i zamiana kolejności dwóch wartości, itd. ◦ np. int zmienna = Interlocked. Increment(ref inna. Zmienna); Atrybut [Synchronization] Inne zagadnienia: Background. Worker, delegat Time. Callback, pula wątków CLR: (Thread. Pool. Queue. User. Work. Item(Wait. Callback wcb) ) 133

Task. Parallel. Library (TPL). NET 4. 0 Nie znaczy to, że Thread czy asynchroniczne Task. Parallel. Library (TPL). NET 4. 0 Nie znaczy to, że Thread czy asynchroniczne delegaty stały się passe, i należy przestać ich używać (jak np. kolekcje bez ) – są i będą wciąż przydatne i nikt nie będzie z nich rezygnować (zbyt szybko). TPL jest „po prostu” wielką armatą, którą wytaczać należy tylko do NAPRAWDĘ skomplikowanych wielowątkowych algorytmów, których użycie ma szansę znacząco skrócić wykonywanie zadań. Bazuje wciąż na starych technikach tutaj zaprezentowanych, więc ich znajomość jest niezbędna w zrozumieniu TPL. 134

Cap. XIV: Pliki, I/O, serializacja 135 Cap. XIV: Pliki, I/O, serializacja 135

System. IO Ważniejsze klasy: Binary. Reader Binary. Writer Directory. Info File. Stream File. System. System. IO Ważniejsze klasy: Binary. Reader Binary. Writer Directory. Info File. Stream File. System. Watcher Memory. Stream Path Stream. Writer Stream. Reader String. Writer String. Reader abstract File. System. Info: ◦ Attributes atrybuty pliku / katalogu ◦ Creation. Time czas utworzenia ◦ Exists czy obiekt istnieje? ◦ Extension rozszerzenie ◦ Full. Name pełna ścieżka dostępu ◦ Last. Access. Time ostatni dostęp ◦ Last. Write. Time ostatnia modyfikacja ◦ Name nazwa pliku / katalogu 136

c. d. Directory. Info: ◦ Create() ◦ Create. Subdirectory() ◦ Delete() tworzenie katalogu lub c. d. Directory. Info: ◦ Create() ◦ Create. Subdirectory() ◦ Delete() tworzenie katalogu lub zbioru podkatalogów kasuje katalog i całą zawartość ◦ Get. Directories() tablica obiektów Directory. Info o zawartości katalogu ◦ Get. Files() tablica File. Info z zawartości katalogu ◦ Move. To() przenoszenie do nowej ścieżki ◦ Parent zwraca katalog nadrzędny ◦ Root zwraca ścieżkę do korzenia katalogu // Bind to the current working directory. Directory. Info dir 1 = new Directory. Info(". "); // Bind to C: Windows, // using a verbatim string. Directory. Info dir 2 = new Directory. Info(@"C: Windows"); 137

 Przykład: Directory. Info dir = new Directory. Info(@ Przykład: Directory. Info dir = new Directory. Info(@"C: Windows"); Console. Write. Line("***** Directory Info *****"); Console. Write. Line("Full. Name: {0}", dir. Full. Name); Console. Write. Line("Name: {0}", dir. Name); Console. Write. Line("Parent: {0}", dir. Parent); Console. Write. Line("Creation: {0}", dir. Creation. Time); Console. Write. Line("Attributes: {0}", dir. Attributes); Console. Write. Line("Root: {0}", dir. Root); Console. Write. Line("*************n"); Wynik: ***** Directory Info ***** Full. Name: C: Windows Name: Windows Parent: Creation: 7/13/2009 10: 20: 08 PM Attributes: Directory Root: C: ************* 138

Pobieranie listy plików: Directory. Info dir = new Directory. Info(@ Pobieranie listy plików: Directory. Info dir = new Directory. Info(@"C: WindowsWebWallpaper"); // pobierz wszystkie pliki jpg: File. Info[] image. Files = dir. Get. Files("*. jpg", Search. Option. All. Directories); // ile znaleziono? : Console. Write. Line("Found {0} *. jpg filesn", image. Files. Length); foreach (File. Info f in image. Files) { Console. Write. Line("File name: {0}", f. Name); Console. Write. Line("File size: {0}", f. Length); Console. Write. Line("Creation: {0}", f. Creation. Time); Console. Write. Line("Attributes: {0}", f. Attributes); } 139

Tworzenie podkatalogów: Directory. Info dir = new Directory. Info(@ Tworzenie podkatalogów: Directory. Info dir = new Directory. Info(@"C: "); dir. Create. Subdirectory("My. Folder"); Directory. Info my. Data. Folder = dir. Create. Subdirectory(@"My. Folder 2Data"); Console. Write. Line("New Folder is: {0}", my. Data. Folder); 140

// lista dysków: string[] drives = Directory. Get. Logical. Drives(); Console. Write. Line( // lista dysków: string[] drives = Directory. Get. Logical. Drives(); Console. Write. Line("Here are your drives: "); foreach (string s in drives) Console. Write. Line("--> {0} ", s); // kasowanie: try { Directory. Delete(@"C: My. Folder"); // drugie „true” oznacza zgodę na automatyczne kasowanie podkatalogów Directory. Delete(@"C: My. Folder 2", true); } catch (IOException e) { Console. Write. Line(e. Message); } 141

static void Main(string[] args) { // pobranie tablicy obiektów – napędów: Drive. Info[] my. static void Main(string[] args) { // pobranie tablicy obiektów – napędów: Drive. Info[] my. Drives = Drive. Info. Get. Drives(); // wyświetlanie informacji foreach(Drive. Info d in my. Drives) { Console. Write. Line("Name: {0}", d. Name); Console. Write. Line("Type: {0}", d. Drive. Type); // jeśli napęd jest podpięty (DVD, CD, pendrive…) if(d. Is. Ready) { Console. Write. Line("Free space: {0}", d. Total. Free. Space); Console. Write. Line("Format: {0}", d. Drive. Format); Console. Write. Line("Label: {0}", d. Volume. Label); Console. Write. Line(); } } Console. Read. Line(); } 142

Klasa File. Info: static void Main(string[] args) { // utworzenie nowego pliku: File. Info Klasa File. Info: static void Main(string[] args) { // utworzenie nowego pliku: File. Info f 2 = new File. Info(@"C: Test 2. dat"); using(File. Stream fs 2 = f 2. Open(File. Mode. Open. Or. Create, File. Access. Read. Write, File. Share. None)) { //. . } } File. Mode: Create. New, Create, Open. Or. Create, Truncate, Append File. Access: Read, Write, Read. Write File. Share: Delete, Inheritable, None, Read. Write, Write 143

File. Info. Open. Read() File. Info. Open. Write() static void Main(string[] args) { File. File. Info. Open. Read() File. Info. Open. Write() static void Main(string[] args) { File. Info f 3 = new File. Info(@"C: Test 3. dat"); using(File. Stream read. Only. Stream = f 3. Open. Read()) { // File. Stream object. . . } // tylko do zapisu: File. Info f 4 = new File. Info(@"C: Test 4. dat"); using(File. Stream write. Only. Stream = f 4. Open. Write()) { // File. Stream object. . . } } 144

File. Info. Open. Text(), File. Info. Create. Text(), File. Info. Append. Text() File. Info File. Info. Open. Text(), File. Info. Create. Text(), File. Info. Append. Text() File. Info f 5 = new File. Info(@"C: boot. ini"); using(Stream. Reader sreader = f 5. Open. Text()) { // Use the Stream. Reader object. . . } File. Info f 6 = new File. Info(@"C: Test 6. txt"); using(Stream. Writer swriter = f 6. Create. Text()) { // Use the Stream. Writer object. . . } File. Info f 7 = new File. Info(@"C: Final. Test. txt"); using(Stream. Writer swriter. Append = f 7. Append. Text()) { // Use the Stream. Writer object. . . } 145

Klasa File using(File. Stream fs = File. Create(@ Klasa File using(File. Stream fs = File. Create(@"C: Test. dat")) {} using(File. Stream fs 2 = File. Open(@"C: Test 2. dat", File. Mode. Open. Or. Create, File. Access. Read. Write, File. Share. None)) {} using(File. Stream read. Only. Stream = File. Open. Read(@"Test 3. dat")) {} using(File. Stream write. Only. Stream = File. Open. Write(@"Test 4. dat")) {} using(Stream. Reader sreader = File. Open. Text(@"C: boot. ini")) {} using(Stream. Writer swriter = File. Create. Text(@"C: Test 6. txt")) {} using(Stream. Writer swriter. Append = File. Append. Text(@"C: Final. Test. txt")) {} 146

Inne metody klasy File ◦ Read. All. Bytes() – tablica bajtów + zamknięcie pliku Inne metody klasy File ◦ Read. All. Bytes() – tablica bajtów + zamknięcie pliku ◦ Read. All. Lines() – tablica strings + zamknięcie pliku ◦ Read. All. Text() System. String+ zamknięcie pliku Poniżej jak wyżej, tylko że zapisujemy coś: ◦ Write. All. Bytes() ◦ Write. All. Lines() ◦ Write. All. Text() 147

Przykład: static void Main(string[] args) { string[] my. Tasks = { „Naprawić kran Przykład: static void Main(string[] args) { string[] my. Tasks = { „Naprawić kran", „Zadzwonić", „Zjeść coś", „Zagrać w Diablo III"}; // zapis danych: File. Write. All. Lines(@"C: tasks. txt", my. Tasks); // odczyt danych foreach (string task in File. Read. All. Lines(@"C: tasks. txt")) { Console. Write. Line("TODO: {0}", task); } Console. Read. Line(); } 148

File. Stream // Obtain a File. Stream object. using(File. Stream f. Stream = File. File. Stream // Obtain a File. Stream object. using(File. Stream f. Stream = File. Open(@"C: my. Message. dat", File. Mode. Create)) { // zakodowanie wiadomości jako ciągu bajtów string msg = "Hello!"; byte[] msg. As. Byte. Array = Encoding. Default. Get. Bytes(msg); // zapis tablicy bajtów[] f. Stream. Write(msg. As. Byte. Array, 0, msg. As. Byte. Array. Length); // reset położenia „kursora” zapisu f. Stream. Position = 0; // odczyt od „kursora” Console. Write("Your message as an array of bytes: "); byte[] bytes. From. File = new byte[msg. As. Byte. Array. Length]; for (int i = 0; i < msg. As. Byte. Array. Length; i++) { bytes. From. File[i] = (byte)f. Stream. Read. Byte(); Console. Write(bytes. From. File[i]); } Console. Write. Line(Encoding. Default. Get. String(bytes. From. File)); } 149

Trochę łatwiej (i popularniej jeśli chodzi o stosowanie): Stream. Writer i Stream. Reader using(Stream. Trochę łatwiej (i popularniej jeśli chodzi o stosowanie): Stream. Writer i Stream. Reader using(Stream. Writer writer = File. Create. Text("reminders. txt")) { writer. Write. Line(„Tekst pierwszy"); writer. Write. Line(„Tekst drugi"); writer. Write. Line(„Ciąg liczb: "); for(int i = 0; i < 10; i++) writer. Write(i + " "); // nowa linia: writer. Write(writer. New. Line); } using(Stream. Reader sr = File. Open. Text("reminders. txt")) { string input = null; while ((input = sr. Read. Line()) != null) { Console. Write. Line (input); } } 150

Inna wersja z poprzedniego przykładu: // zapis: using(Stream. Writer writer = new Stream. Writer( Inna wersja z poprzedniego przykładu: // zapis: using(Stream. Writer writer = new Stream. Writer("reminders. txt")) {. . . } // odczyt: using(Stream. Reader sr = new Stream. Reader("reminders. txt")) {. . . } 151

Binary. Writer i Binary. Reader File. Info f = new File. Info( Binary. Writer i Binary. Reader File. Info f = new File. Info("Bin. File. dat"); using(Binary. Writer bw = new Binary. Writer(f. Open. Write())) { Console. Write. Line("Base stream is: {0}", bw. Base. Stream); // dane: double a. Double = 1234. 67; int an. Int = 34567; string a. String = "A, B, C"; // zapis danych: bw. Write(a. Double); bw. Write(an. Int); bw. Write(a. String); } using(Binary. Reader br = new Binary. Reader(f. Open. Read())) { Console. Write. Line(br. Read. Double()); Console. Write. Line(br. Read. Int 32()); Console. Write. Line(br. Read. String()); } 152

File. System. Watcher Klasa zawiera metody do monitorowania co się dzieje z plikiem (tadam, File. System. Watcher Klasa zawiera metody do monitorowania co się dzieje z plikiem (tadam, tadam!): asynchronicznie Np. utworzenie takiego obiektu to: File. System. Watcher watcher = new File. System. Watcher(); try { watcher. Path = @"C: My. Folder"; } catch(Argument. Exception ex) { Console. Write. Line(ex. Message); return; } 153

c. d. Co ma być monitorowane i jak: // Set up the things to c. d. Co ma być monitorowane i jak: // Set up the things to be on the lookout for. watcher. Notify. Filter = Notify. Filters. Last. Access | Notify. Filters. Last. Write | Notify. Filters. File. Name | Notify. Filters. Directory. Name; // Only watch text files. watcher. Filter = "*. txt"; // Add event handlers. watcher. Changed += new File. System. Event. Handler(On. Changed); watcher. Created += new File. System. Event. Handler(On. Changed); watcher. Deleted += new File. System. Event. Handler(On. Changed); watcher. Renamed += new Renamed. Event. Handler(On. Renamed); // Begin watching the directory. watcher. Enable. Raising. Events = true; // TUTAJ INNY KOD, KTÓRY ROBI JUŻ W PROGRAMIE CO INNEGO, ALE WATCHER DZIAŁA, I JEŚLI COŚ SIĘ STANIE Z PLIKIEM CO ZOSTAŁO OKREŚLONE WYŻEJ, ODPALI SIĘ ODPOWIEDNIA Z METOD NIŻEJ: Metody: static void On. Changed(object source, File. System. Event. Args e) { Console. Write. Line("File: {0} {1}!", e. Full. Path, e. Change. Type); } static void On. Renamed(object source, Renamed. Event. Args e) { Console. Write. Line("File: {0} renamed ton{1}", e. Old. Full. Path, e. Full. Path); } 154

Serializacja: Poprzednie metody zapisu i odczytu plików są ok. i powszechnie stosowane. Problem pojawia Serializacja: Poprzednie metody zapisu i odczytu plików są ok. i powszechnie stosowane. Problem pojawia się, kiedy nieokreśloną (np. na poziomie projektowania czegoś) liczbę parametrów aplikacji trzeba będzie zapisywać, odczytywać, itd. Dla każdego parametru należałoby wtedy wprowadzać osobne linie kodu obsługujące jego zapis/odczyt. 155

Przykład serializacji: [Serializable] public class User. Prefs { public string Window. Color; public int Przykład serializacji: [Serializable] public class User. Prefs { public string Window. Color; public int Font. Size; } static void Main(string[] args) { User. Prefs user. Data= new User. Prefs(); user. Data. Window. Color = "Yellow"; user. Data. Font. Size = "50"; Binary. Formatter bin. Format = new Binary. Formatter(); // zapis obiektu w pliku: using(Stream f. Stream = new File. Stream("user. dat", File. Share. None)) File. Mode. Create, File. Access. Write, { bin. Format. Serialize(f. Stream, user. Data); } Console. Read. Line(); } 156

Co serializować a co nie (instrukcje w kodzie, a nie porady życiowe) [Serializable] public Co serializować a co nie (instrukcje w kodzie, a nie porady życiowe) [Serializable] public class Radio { public bool has. Tweeters; public bool has. Sub. Woofers; public double[] station. Presets; [Non. Serialized] public string radio. ID = "XF-552 RR 6"; } [Serializable] public class Car { public Radio the. Radio = new Radio(); public bool is. Hatch. Back; } [Serializable] public class James. Bond. Car : Car { public bool can. Fly; public bool can. Submerge; } 157

Kolejna informacja co będzie a co nie będzie serializowane Binary. Formatter lub Soap. Formatter Kolejna informacja co będzie a co nie będzie serializowane Binary. Formatter lub Soap. Formatter – te narzędzia serializują WSZYSTKO co podpada pod tag [serializable] w kodzie, tj. niezależnie czy są to pola publiczne, prywatne, publiczne właściwości prywatne, itd. Xml. Serializer – trochę inaczej. Będzie serializować tylko pola publiczne a także (uwaga!) prywatne dane które zostały udostępnione jako publiczne właściwości (czyli zmienna jeśli nawet jest private, to jeśli jej właściwość get jest publiczna, zostanie przez Xml. Serializer przetworzona). 158

[Serializable] public class Person { // A public field. public bool is. Alive = [Serializable] public class Person { // A public field. public bool is. Alive = true; // A private field. private int person. Age = 21; // Public property/private data. private string f. Name = string. Empty; public string First. Name { get { return f. Name; } set { f. Name = value; } } } 159

Różnice serializatorów Binary. Formatter – jak nazwa wskazuje, zapisuje binarnie, czyli np. liczba zapisana Różnice serializatorów Binary. Formatter – jak nazwa wskazuje, zapisuje binarnie, czyli np. liczba zapisana jest szesnastkowo, a nie w formie tekstu Soap. Formatter – jako wiadomość typu SOAP (XMLowy format przesyłania wiadomości w web service’ach) Xml. Serializer – XML, jak nazwa wskazuje, czyli otagowany całkowicie 160

Przykład serializacji binarnej: static void Main(string[] args) { James. Bond. Car jbc = new Przykład serializacji binarnej: static void Main(string[] args) { James. Bond. Car jbc = new James. Bond. Car(); //4 slajdy wcześniej jbc. can. Fly = true; jbc. can. Submerge = false; jbc. the. Radio. station. Presets = new double[]{89. 3, 105. 1, 97. 1}; jbc. the. Radio. has. Tweeters = true; // zapis do pliku: Binary. Formatter bin. Format = new Binary. Formatter(); using(Stream f. Stream = new File. Stream("Car. Data. dat", File. Mode. Create, File. Access. Write, File. Share. None)) { bin. Format. Serialize(f. Stream, jbc); } //odczyt: Binary. Formatter bin. Format = new Binary. Formatter(); using(Stream f. Stream = File. Open. Read("Car. Data. dat"))) { James. Bond. Car car. From. Disk = (James. Bond. Car)bin. Format. Deserialize(f. Stream); Console. Write. Line("Can this car fly? : {0}", car. From. Disk. can. Fly); } 161

Zapis listy obiektów [Serializable, Xml. Root(Namespace = Zapis listy obiektów [Serializable, Xml. Root(Namespace = "http: //www. My. Company. com")] public class James. Bond. Car : Car { public James. Bond. Car(bool sky. Worthy, bool sea. Worthy) { can. Fly = sky. Worthy; can. Submerge = sea. Worthy; } // Xml. Serializer WYMAGA domyślnego konstruktora! public James. Bond. Car(){} } 162

static void Save. List. Of. Cars() { // Now persist a List<T> of James. static void Save. List. Of. Cars() { // Now persist a List of James. Bond. Cars. List my. Cars = new List(); my. Cars. Add(new James. Bond. Car(true, true)); my. Cars. Add(new James. Bond. Car(true, false)); my. Cars. Add(new James. Bond. Car(false, true)); my. Cars. Add(new James. Bond. Car(false, false)); using(Stream f. Stream = new File. Stream("Car. Collection. xml", File. Mode. Create, File. Access. Write, File. Share. None)) { Xml. Serializer xml. Format = new Xml. Serializer(typeof(List)); xml. Format. Serialize(f. Stream, my. Cars); } } // LUB: static void Save. List. Of. Cars. As. Binary() { // Save Array. List object (my. Cars) as binary. List my. Cars = new List(); Binary. Formatter bin. Format = new Binary. Formatter(); using(Stream f. Stream = new File. Stream("All. My. Cars. dat", File. Mode. Create, File. Access. Write, File. Share. None)) { bin. Format. Serialize(f. Stream, my. Cars); } } 163

ISerializable [Serializable] class String. Data : ISerializable { private string data. Item. One = ISerializable [Serializable] class String. Data : ISerializable { private string data. Item. One = "First data block"; private string data. Item. Two= "More data"; public String. Data(){} protected String. Data(Serialization. Info si, Streaming. Context ctx) { //zawsze odczytuj mały literami data. Item. One = si. Get. String("First_Item"). To. Lower(); data. Item. Two = si. Get. String("data. Item. Two"). To. Lower(); } void ISerializable. Get. Object. Data(Serialization. Info info, Streaming. Context ctx) { //zawsze zapisuj dużymi literami info. Add. Value("First_Item", data. Item. One. To. Upper()); info. Add. Value("data. Item. Two", data. Item. Two. To. Upper()); } } 164

Iserializable c. d. static void Main(string[] args) { String. Data my. Data = new Iserializable c. d. static void Main(string[] args) { String. Data my. Data = new String. Data(); Soap. Formatter soap. Format = new Soap. Formatter(); using(Stream f. Stream = new File. Stream("My. Data. soap", File. Mode. Create, File. Access. Write, File. Share. None)) { soap. Format. Serialize(f. Stream, my. Data); } Console. Read. Line(); } 165

Albo poprzez atrybuty (bez dziedziczenia z Iserializable): [Serializable] class More. Data { private string Albo poprzez atrybuty (bez dziedziczenia z Iserializable): [Serializable] class More. Data { private string data. Item. One = "First data block"; private string data. Item. Two= "More data"; [On. Serializing] private void On. Serializing(Streaming. Context context) { // Called during the serialization process. data. Item. One = data. Item. One. To. Upper(); data. Item. Two = data. Item. Two. To. Upper(); } [On. Deserialized] private void On. Deserialized(Streaming. Context context) { // Called once the deserialization process is complete. data. Item. One = data. Item. One. To. Lower(); data. Item. Two = data. Item. Two. To. Lower(); } } 166