33
---------- Računarski praktikum 3 ---------- Maja Starčević 1 25/05/22 RP3/predavanje09 Imenički prostori Anonimni tipovi i metode Lambda izrazi LINQ Finalizatori

RP3/predavanje09

Embed Size (px)

DESCRIPTION

RP3/predavanje09. Imenički prostori Anonimni tipovi i metode Lambda izrazi LINQ Finalizatori. Imenički prostori. Imenički prostor (engl. namespace ) je područje unutar kojeg svako ime tipa mora biti jedinstveno. - PowerPoint PPT Presentation

Citation preview

Page 1: RP3/predavanje09

---------- Računarski praktikum 3 ----------Maja Starčević

124/04/23

RP3/predavanje09

Imenički prostori Anonimni tipovi i metode Lambda izrazi LINQ Finalizatori

Page 2: RP3/predavanje09

-------Računarski praktikum 3------- 224/04/23

Imenički prostori

Imenički prostor (engl. namespace) je područje unutar kojeg svako ime tipa mora biti jedinstveno.

Tipovi su organizirani u hijerarhijske imeničke prostore. Imenički prostori nemaju utjecaj na vidljivost članova.

Za tipove koji nisu smješteni ni u jednom imeničkom prostoru kaže se da se nalaze u globalnom imeničkom prostoru koji sadrži sve najviše rangirane imeničke prostore.

Page 3: RP3/predavanje09

-------Računarski praktikum 3------- 324/04/23

Imenički prostori

namespace Outer{ namespace Middle { namespace Inner { class Class1 { … } class Class2 { … } } }}

namespace Outer.Middle.Inner{ class Class1 { … } class Class2 { … } }

Pozivanje klaseOuter.Middle.Inner.Class1

Page 4: RP3/predavanje09

Imenički prostori

Da bismo naznačili da se ime nalazi u globalnom prostoru imena, koristimo ključnu riječ global.

-------Računarski praktikum 3------- 424/04/23

global::System.Drawing.Color color;

Napomena: deklaracija nekog prostora imena se može ponoviti više puta. Bitno je da te deklaracije ne sadrže tipove s istim imenom.

Page 5: RP3/predavanje09

Imenički prostori

-------Računarski praktikum 3------- 524/04/23

Možemo i koristiti drugo (kraće) ime za neki prostor.

using DrawingColor=System.Drawing.Color;

class Program { DrawingColor color; }

using StringBuilder=System.Text.StringBuilder;

Pomoću using možemo zadati i kraće ime za neki tip. Ne moramo dakle uključiti cijeli prostor System.Text.

Page 6: RP3/predavanje09

Imenički prostori

-------Računarski praktikum 3------- 624/04/23

using System;

namespace System{ namespace System {

class Console { void f() { } }

class Program { static void Main(string[] args) { Console.WriteLine( “Hello!”); System.Console.WriteLine("Hello!"); System.System.Console.WriteLine("Hello!"); } } }}

Primjer 1:

Koji je pozivfunkcijeWriteLinekorektan?

Page 7: RP3/predavanje09

Imenički prostori

-------Računarski praktikum 3------- 724/04/23

using System;

namespace System // ovaj prostor je već prethodno definiran{ (ovdje se nalazi klasa Console koju smo dosad koristili) namespace System // ovaj prostor smo sami definirali {

class Console { void f() { } }

class Program { static void Main(string[] args) { Console.WriteLine( “Hello!”); // greška System.Console.WriteLine("Hello!"); //greška System.System.Console.WriteLine("Hello!"); //greška global::System.Console.WriteLine( “Hello!”); // u redu } } }}

Page 8: RP3/predavanje09

-------Računarski praktikum 3------- 824/04/23

Verzija C# 3.0

Od ove verzije dostupni su i sljedeći elementi programa:

Lambda izraziMetode proširenjaImplicitno dodjeljivanje tipovaPrepoznavanje upitaAnonimni tipoviImplicitno zadavanje poljaInicijalizacija objekata i kolekcijaAutomatski implementirana svojstva

Page 9: RP3/predavanje09

-------Računarski praktikum 3------- 924/04/23

Anonimni tipovi

class Program{ public delegate int Delegat(int i);

static public int sqr(int a) { return a * a ; }

static public void Main() { int j = 2; Delegat d = sqr; Console.Write(d(2)); } }

Sljedeći primjer ćemo zapisati jednostavnije, pomoću anonimnih tipova:

Page 10: RP3/predavanje09

-------Računarski praktikum 3------- 1024/04/23

Anonimni tipovi

class Program { public delegate int Delegat(int i);

static public void Main() { Delegat d = delegate(int a) { return a * a; }; int j = 2; Console.Write(d(2)); } }

Jednostavnija verzija:

Page 11: RP3/predavanje09

-------Računarski praktikum 3------- 1124/04/23

Lambda izrazi

class Program { public delegate int Delegat(int i); static public void Main() {

Delegat d = a => a*a; int j = 2; Console.Write(d(2)); } }

Pomoću lambda izraza moguće je kod zapisati još jednostavnije:

Page 12: RP3/predavanje09

-------Računarski praktikum 3------- 1224/04/23

Lambda izrazi

Napomena: opća forma lambda izraza je:

U prethodnom primjeru možemo pisati i:

Delegat d = (int a) => a*a;

ili bez eksplicitnog navođenja tipova, i bez zagrada (kad se radi o samo jednom parametru)

Delegat d = a => {return a*a; };

(popis parametara) => izraz ili blok naredbi

Page 13: RP3/predavanje09

-------Računarski praktikum 3------- 1324/04/23

Func i Action delegati

U prostoru System definirano je više (preopterećenih) generičkih delegata s imenom Func i Action, npr.:

delegate TResult Func<TResult> ();delegate TResult Func <T, TResult>(T arg1);itd.

delegate void Action();delegate void Action<T1, T2>(T1 arg1, T2 arg2);itd.

Page 14: RP3/predavanje09

-------Računarski praktikum 3------- 1424/04/23

Func i Action delegati

Koristeći tako definirane generičke delegate, prethodni kodmožemo pisati na još jednostavniji način:

Func<int, int> sqr = x => x * x;Console.WriteLine(sqr(2));

Page 15: RP3/predavanje09

-------Računarski praktikum 3------- 1524/04/23

Metode proširenja

Ukoliko želimo dodavati metode u već definiranu klasu, a modifikacija klase nije dozvoljena ili je zapečaćena pa se ne može ni nasljeđivati, možemo to učiniti pomoću metoda proširenja. Ako je klasa definirana pomoću modifikatora partial, možemo dodati metodu i u drugi dio klase.

Metoda proširenja je statička metoda (negeneričke) statičke klase. Sama metoda može biti generička. Na prvi parametar takve metode je potrebno primijeniti modifikator this.

Page 16: RP3/predavanje09

-------Računarski praktikum 3------- 1624/04/23

Metode proširenja public class DPoint { public double x, y; public DPoint(double _x, double _y) { x = _x; y = _y; } }

public static class DodatneMetode { public static double Udaljenost(this DPoint cp1, DPoint cp2) { return Math.Sqrt(Math.Pow(cp1.x - cp2.x,2) + Math.Pow(cp1.y - cp2.y, 2)); } }

Page 17: RP3/predavanje09

-------Računarski praktikum 3------- 1724/04/23

Metode proširenja

class Program{ static void Main(string[] args) {

DPoint p1 = new DPoint(2, 4); DPoint p2 = new DPoint(6, 1); Console.WriteLine(p1.Udaljenost(p2)); // ili… Console.WriteLine(DodatneMetode.Udaljenost(p1, p2)); }}

Page 18: RP3/predavanje09

-------Računarski praktikum 3------- 1824/04/23

Implicitno zadavanje polja

var studenti = new[] { new { Ime="Petar", Prezime="Peric“ }, new { Ime="Karlo", Prezime="Karlovic“ } };

foreach (var student in studenti) Console.WriteLine(student.Ime);

U sljedećem primjeru imamo polje koje sadrži objekte anonimnog tipa. Umjesto tipa polja, navodimo var.

Page 19: RP3/predavanje09

-------Računarski praktikum 3------- 1924/04/23

LINQ

U LINQ-u pod nizom smatramo objekt tipa koji implementira generičko IEnumerable sučelje.Operator upita je metoda koja transformira niz.

Operatori upita se nalaze u statičkoj klasi Enumerable (nalazi se u prostoru System.Linq). Radi se o statičkim generičkim metodama koje su zapravo metode proširenja za klase tipa IEnumerable<>. Primjer: metoda Where pomoću koje iz početnog niza dobivamo podskup s određenim svojstvima koje smo zadali lambda izrazom.

public static IEnumerable<TSource> Where<TSource>( this IEnumerable<TSource> source, Func<TSource, bool> predicate )

Page 20: RP3/predavanje09

-------Računarski praktikum 3------- 2024/04/23

LINQ

string[] imena = { "Mirko", "Marko", "Mario", "Karlo", "Marina", "Ivona" };

IEnumerable<string> imenaKojaPocinjuNaMa = System.Linq.Enumerable.Where(imena, n => n.StartsWith("Ma"));

/* ili IEnumerable<string> imenaKojaPocinjuNaMa = imena.Where(n => n.StartsWith("Ma")); */

foreach (string ime in imenaKojaPocinjuNaMa) Console.WriteLine(ime);

S obzirom da radimo s metodama proširenja, možemo ih pozivati na dva načina.

Page 21: RP3/predavanje09

-------Računarski praktikum 3------- 2124/04/23

LINQ

int[] brojevi = new int[] { 1, 2, 3, 4, 5 }; IEnumerable<int> dvostrukiBrojevi= brojevi.Select(n => n * 2); foreach (int i in dvostrukiBrojevi) Console.Write("{0} ", i); // 2 4 6 8 10

Pomoću metode Select transformiramo svaki element početnog niza po pravilu zadanom lambda izrazom.

Page 22: RP3/predavanje09

-------Računarski praktikum 3------- 2224/04/23

LINQ

Nizove možemo mijenjati koristeći lambda sintaksu koju smo vidjeli u prethodnim primjerima ili sintaksu upita ili u nekim slučajevima njihovu kombinaciju. Zapisat ćemo prvi primjer u drugoj sintaksi.

string[] imena = { "Mirko", "Marko", "Mario", "Karlo", "Marina", "Ivona" }; IEnumerable<string> imenaKojaPocinjuNaMa = from n in imena where n.StartsWith("Ma") select n;

foreach (string ime in imenaKojaPocinjuNaMa) Console.WriteLine(ime);

Page 23: RP3/predavanje09

-------Računarski praktikum 3------- 2324/04/23

LINQusing System;using System.Collections.Generic;using System.Linq;using System.Text.RegularExpressions;

class Program { static void Main(string[] args) { string[] rijeci = { "kap", "vrt", "krt", "pol", "krv" };

IEnumerable<string> rijeciBezSamoglasnika = from n in rijeci let rijecBezSamoglasnika = Regex.Replace(n, "[aeiou]", "") where n == rijecBezSamoglasnika select n;

foreach (string rijec in rijeciBezSamoglasnika) Console.WriteLine(rijec); } }

vrtkrtkrv

S ključnom riječi let uvodimo novu varijablu.

Page 24: RP3/predavanje09

-------Računarski praktikum 3------- 2424/04/23

LINQ

char[] slova = { 'a', 'b', 'c' }; int[] brojevi = { 1, 2, 3, };

IEnumerable<string> clanovi = from n in slova from m in brojevi select n + m.ToString();

foreach (string s in clanovi) Console.Write(s + " "); a1 a2 a3 b1 b2 b3 c1 c2 c3

Upit može sadržavati više from iskaza, koji onda funkcioniraju poput ugniježdene petlje.

Page 25: RP3/predavanje09

-------Računarski praktikum 3------- 2524/04/23

LINQ

char[] slova = { 'a', 'b', 'c' }; List<int> brojevi = new List<int>{ 1, 2, 3, };

IEnumerable<string> clanovi = from n in slova from m in brojevi select n + m.ToString(); brojevi.Add(4);

foreach (string s in clanovi) Console.Write(s + " "); a1 a2 a3 a4 b1 b2 b3 b4 c1 c2 c3 c4

Mnogi operatori upita funkcioniraju tako da se ne izvršavaju prikreiranju, nego kad se na enumeratoru rezultata pozove metoda MoveNext (npr. kad u sljedećem primjeru prođemo kroz niz s foreach).

Page 26: RP3/predavanje09

-------Računarski praktikum 3------- 2624/04/23

Destruktor (metoda Finalize)

Implementacija destruktora u klasi je zapravo nadjačavanje object.Finalize metode.

Destruktori se mogu naći samo u klasama, strukture ih ne mogu sadržavati.

Page 27: RP3/predavanje09

-------Računarski praktikum 3------- 2724/04/23

Destruktor (metoda Finalize)

class C{ ~C() { // implementacija}}

class C{ protected void override Finalize() { // implementacija; base.Finalize(); }}

je zapravo kraći zapis za:

Napomena: kompilator dozvoljava samo prvi način zapisa.

Page 28: RP3/predavanje09

-------Računarski praktikum 3------- 2824/04/23

Dispose, Finalize

Finalizator funkcionira slično destruktoru u C++-u s tom razlikomda se za upravljane resurse brine Garbage Collector te se finalizatori implementiraju jedino u slučaju da se moramopobrinuti za uništavanje neupravljanih resursa.Finalizator se ne smije pozivati eksplicitno, njega će pozvati GCkad odluči uništiti objekt.Ukoliko ipak želimo neupravljane resurse uništiti čim prije,moramo implementirati metodu Dispose. Ukoliko, klasaimplementira metodu Dispose, preporučljivo je da implementiraIDisposable sučelje.

Page 29: RP3/predavanje09

-------Računarski praktikum 3------- 2924/04/23

Dispose, Finalize

Sljedeći primjer daje standardni način pisanja Finalize metodeu kombinaciji s Dispose metodom.

Klasa C implementira Dispose u dvije preopterećene varijante. Javna metoda void Dispose() je namijenjena za korisnike, njome se naređuje što prije uništavanje neupravljanih resursa.I ta metoda i finalizator se baziraju na void Dispose (bool) metodi.Dispose(true) se poziva u javnoj Dispose metodi, a Dispose(false) u finalizatoru. Dakle, čišćenje objekta teče na isti način.

Page 30: RP3/predavanje09

-------Računarski praktikum 3------- 3024/04/23

Dispose, Finalize

Preko bool disposing dakle samo kontroliramo je li pozvan finalizator (naravno implicitno) ili Dispose metoda.

Osigurač bool is_disposed sprječava višestruko izvršavanjeDispose metode, odnosno dozvoljava da ju korisnik moževiše puta pozivati na istom objektu, ali da se samo prvi put dogodi čišćenje.

Ukoliko je pozvana Dispose metoda, GC neće pozivatifinalizator što se postiže pozivomGC.SupressFinalize metode.

Page 31: RP3/predavanje09

-------Računarski praktikum 3------- 3124/04/23

Dispose, Finalize

class C {

bool is_disposed = false; protected virtual void Dispose(bool disposing) { if (!is_disposed) { if (disposing) { Console.WriteLine("Ovo je Dispose, a ne Finalize"); }

//čišćenje objekta } is_disposed = true; }

public void Dispose() { Dispose(true); GC.SuppressFinalize(this); }

~C() { Dispose(false); Console.WriteLine("U finalizatoru smo"); }

}

Page 32: RP3/predavanje09

-------Računarski praktikum 3------- 3224/04/23

Dispose, using

using (C obj = new C( ) ) { ……… }

U prethodnom kontekstu ključna riječ using ima novo značenje.

Konkretno, kod

je ekvivalentan s:

Page 33: RP3/predavanje09

-------Računarski praktikum 3------- 3324/04/23

Dispose, Finalize

C obj = new C(); try {

……….. } finally { if (obj != null) ((IDisposable)obj).Dispose(); }