Nové prvky v C# 3.0. David Keprt



Podobné dokumenty
Univerzita Palackého v Olomouci Radek Janoštík (Univerzita Palackého v Olomouci) Základy programování 4 - C# 3.4.

Jazyk C# (seminář 6)

PŘETĚŽOVÁNÍ OPERÁTORŮ

PREPROCESOR POKRAČOVÁNÍ

Třídy. Instance. Pokud tento program spustíme, vypíše následující. car1 má barvu Red. car2 má barvu Red. car1 má barvu Blue.

Statické proměnné a metody. Tomáš Pitner, upravil Marek Šabo

Obsah přednášky 7. Základy programování (IZAPR) Přednáška 7. Parametry metod. Parametry, argumenty. Parametry metod.

IRAE 07/08 Přednáška č. 1

Úvod Třídy Rozhraní Pole Konec. Programování v C# Hodnotové datové typy, řídící struktury. Petr Vaněček 1 / 39

Základy jazyka C# Obsah přednášky. Architektura.NET Historie Vlastnosti jazyka C# Datové typy Příkazy Prostory jmen Třídy, rozhraní

Algoritmizace a programování

Výčtový typ strana 67

Generické programování

LINQ. (Language integrated query) Prezentace na 3IT353. Zpracovali: Martin Latiak, Michal Pěnka, Petr Spurný

Zapouzdření. Tomáš Pitner, upravil Marek Šabo

Jazyk C# a platforma.net

PB161 Programování v jazyce C++ Přednáška 7

PB161 Programování v jazyce C++ Přednáška 7

Jazyk C# - přístup k datům

Stream API. Petr Krajča. Základy programovaní 4 (Java) Katedra informatiky Univerzita Palackého v Olomouci

20. Projekt Domácí mediotéka

IRAE 07/08 Přednáška č. 2. atr1 atr2. atr1 atr2 -33

Obsah přednášky 9. Skrývání informací. Skrývání informací. Zapouzdření. Skrývání informací. Základy programování (IZAPR, IZKPR) Přednáška 9

TŘÍDY POKRAČOVÁNÍ. Události pokračování. Příklad. public delegate void ZmenaSouradnicEventHandler (object sender, EventArgs e);

1. Programování proti rozhraní

Úvod do programovacích jazyků (Java)

typová konverze typová inference

Kapitola 1 Začínáme se Silverlightem

Programování II. Návrh programu I 2018/19

Zápis programu v jazyce C#

1 - Úvod do platformy.net. IW5 - Programování v.net a C#

7. přednáška - třídy, objekty třídy objekty atributy tříd metody tříd

Úvod do programovacích jazyků (Java)

Více o konstruktorech a destruktorech

Abstraktní třída a rozhraní

Univerzita Palackého v Olomouci Radek Janoštík (Univerzita Palackého v Olomouci) Základy programování 4 - C# 10.4.

Jazyk C# (seminář 3)

Dědění, polymorfismus

11. Přehled prog. jazyků

Reaktivní programování v.net

Pokročilé programování v jazyce C pro chemiky (C3220) Statické proměnné a metody, šablony v C++

Pokud zadání nerozumíte nebo se vám zdá nejednoznačné, zeptejte se. Pište čitelně, nečitelná řešení nebudeme uznávat.

Programování v Javě I. Únor 2009

Kolekce, cyklus foreach

JAVA. Další jazyky kompilovatelné do Java byte-code

PB161 Základy OOP. Tomáš Brukner

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

Jazyk C# (seminář 3)

NPRG031 Programování II 1 / :25:46

NMIN201 Objektově orientované programování 1 / :36:09

Pokud neuvedeme override, vznikne v synu nová (nevirtuální) metoda (a pochopitelně se nezavolá, jak bychom

Programovací jazyk C# Verze jazyka 3.0

Programovací jazyk. Ing. Marek Běhálek Katedra informatiky FEI VŠB-TUO A-1018 /

Programovací jazyk C# Verze jazyka 3.0

UJO Framework. revoluční architektura beans. verze

Platforma Java. Petr Krajča. Katedra informatiky Univerzita Palackého v Olomouci. Petr Krajča (UP) KMI/PJA: Seminář V. 27. říjen, / 15

2) Napište algoritmus pro vložení položky na konec dvousměrného seznamu. 3) Napište algoritmus pro vyhledání položky v binárním stromu.

8 Třídy, objekty, metody, předávání argumentů metod

Datové typy v Javě. Tomáš Pitner, upravil Marek Šabo

Úvod Přetěžování Generika Kolekce Konec. Programování v C# Další jazykové konstrukce. Petr Vaněček 1 / 31

Pokud zadání nerozumíte nebo se vám zdá nejednoznačné, zeptejte se. Pište čitelně, nečitelná řešení nebudeme uznávat.

IAJCE Přednáška č. 8. double tprumer = (t1 + t2 + t3 + t4 + t5 + t6 + t7) / 7; Console.Write("\nPrumerna teplota je {0}", tprumer);

Programování v C++ 2, 4. cvičení

Programování v Javě I. Leden 2008

Dolování v objektových datech. Ivana Rudolfová

Quo vadis programování? Automatizace vyhodnocování studentských úloh

Pokud zadání nerozumíte nebo se vám zdá nejednoznačné, zeptejte se. Pište čitelně, nečitelná řešení nebudeme uznávat.

Bridge. Známý jako. Účel. Použitelnost. Handle/Body

Principy objektově orientovaného programování

III/2 Inovace a zkvalitnění výuky prostřednictvím ICT

IRAE 07/08 Přednáška č. 7. Začátek (head)

Remote Method Invocation RMI

Konstruktory a destruktory

Úvod do programování - Java. Cvičení č.4

Pole a kolekce. v C#, Javě a C++

Seminář Java II p.1/43

Třídy a objekty. Třídy a objekty. Vytvoření instance třídy. Přístup k atributům a metodám objektu. $z = new Zlomek(3, 5);

Google Web Toolkit. Martin Šurkovský, SUR března Katedra informatiky

KTE / ZPE Informační technologie

Z. Kotala, P. Toman: Java ( Obsah )

Jazyk C++ II. Šablony a implementace

Tabulka symbolů. Vazba (binding) Vazba - příklad. Deklarace a definice. Miroslav Beneš Dušan Kolář

Objektově orientované programování

zapište obslužnou metodu události Click tlačítka a vyzkoušejte chování polevýsledek.text = polečíslo1.text + polečíslo2.text;

SOUBORY, VSTUPY A VÝSTUPY POKRAČOVÁNÍ

public static void main(string[] args) { System.out.println(new Main().getClass().getAnnotation(Greet.class).text());

IB111 Programování a algoritmizace. Objektově orientované programování (OOP)

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

Využití OOP v praxi -- Knihovna PHP -- Interval.cz

Programovací jazyk Java

Abstraktní datové typy: zásobník

Anotace a Hibernate. Aleš Nosek Ondřej Vadinský Daniel Krátký

Jazyk C++ I. Polymorfismus

Kolekce ArrayList. Deklarace proměnných. Import. Vytvoření prázdné kolekce. napsal Pajclín

Programování v C++ 1, 5. cvičení

Software602 Form Designer

Jazyk C++ I. Šablony 2

Funkční objekty v C++.

Transkript:

Nové prvky v C# 3.0 David Keprt revize Aleš Keprt 11.12.2006

Úvod Obsahem této prezentace je představení nových konstrukcí, které do jazyka C# přináší verze 3.0. Mezi ně patří: Klíčové slovo var Nové možnosti inicializace objektů a kolekcí Anonymní typy Rozšiřující metody Lambda výrazy LINQ

Klíčové slovo var (1/2) Slouží k deklaraci implicitně typovaných proměnných. Příklad: // kód z C# 2.0 int i = 10; string s = "Hello people!"; // kód stejné funkčnosti v C# 3.0 var i = 10; var s = "Hello people!";

Klíčové slovo var (2/2) Překladač vyhodnotí pravou stranu deklarace a najde typ, který daným datům odpovídá. Výsledná proměnná, stejně jako celý jazyk, je stále staticky typovaná (na rozdíl od podobně vypadajícího, ale zcela odlišného výrazu variant známého například z VB 6) Typ je proměnné napevno stanoven při překladu její deklarace, tudíž například následující kód překladač zamítne: var b; b = 1337;

Inicializace objektů a kolekcí (1/2) Nová syntaxe umožňující kratší inicializaci objektů vypadá takto: // kód z C# 2.0 Person p = new Person(); // Create object p.name = "Nick"; // Initialize property Name p.gender = "Male"; // Initialize property Gender p.active = true; // Initialize property Active // kód stejné funkčnosti v C# 3.0 Person p = new Person { Name = "Nick", Gender = "Male", Active = true };

Inicializace objektů a kolekcí (2/2) Podobně lze takto inicializovat i kolekce: // kód z C# 2.0 List<string> animals = new List<string>(); animals.add("monkey"); animals.add("cow"); animals.add("dog"); animals.add("cat"); // kód stejné funkčnosti v C# 3.0 List<string> animals = new List<string> { "monkey", "cow", "dog", "cat" } ;

Anonymní typy (1/3) Nová verze jazyka C# nabízí možnost vytvářet instance jednoduché datové třídy bez nutnosti obtěžovat se její deklarací. Chcete mít v paměti objekt s daty o vašem psu a nemáte deklarovanou žádnou vhodnou třídu? Nevadí! Stačí následující: new {name= Cicina, hair="black", age=6} A máme vytvořenou instanci. Ale co s ní, když pro založení reference potřebujeme udat typ třídy na jejíž instanci ukazuje? Ano! Použijeme implicitně typovanou proměnnou: var kocka = new {name= Cicina, hair="black", age=6};

Anonymní typy (2/3) Při překladu vytvoří stroj něco jako toto: class Anonymous1 { private string _name = "black"; private string _hair = "black"; private int _age = 6; public string name {get { return _name; } set { _name = value; }} public string hair {get { return _hair; } set { _hair = value; }} public int age {get { return _age; } set { _age = value; }} }

Anonymní typy (3/3) Překladač navíc není žádný hlupák, a pokud dále v kódu budeme inicializovat instanci anonymní třídy, pak, pokud názvy datových proměnných a typy udaných hodnot budou stejné, místo vyváření další anonymní třídy vytvoří instanci té, kterou již zná. Mimo jiné to způsobí i to, že implicitně typované reference pak mají stejný typ, takže je možné napsat například následující: var kocka = new {name= Cicina, hair="black", age=6} var psik = new {name= Harik, hair= blue", age=8} kocka = psik; Console.WriteLine( Cicina uz neni, {0} ji sezral!, kocka.name);

Rošiřující metody (1/2) Rozšiřující metody jsou zvláštní nástroj umožňující rozšířit již existující třídu o další metody. Tímto nástrojem lze do třídy přidat jen statické metody. Ty pak nemají přístup do privátních dat a nedědí se Volají se však, jakoby statické nebyly Navíc jak víme, je snadné původní třídu podědit a novou metodu přidat do potomka, tak k čemu je tento nástroj? Jeho využitelnost máme ocenit při práci s třídami, které nechceme nebo nemůžeme dědit.

Rošiřující metody (2/2) Pro ilustraci uvedeme příklad doplnění třídy String: public static class StringExtensions { public static int ToInt(this string s) { return Int32.Parse(s); } } Po zkompilování výše uvedeného budou mít všechny stringy v naší aplikaci novou metodu, která jejich obsah přeparsuje na integer. string input = 12345 ; int value = input.toint();

Lambda výrazy (1/5) Již první verze jazyka C# nám umožnovala předávat metodám jako parametr jiné metody pomocí delegátů. // kód z C# 1.0 class Program { } delegate void DemoDelegate(); static void Main(string[] args) { } DemoDelegate mydelegate = new DemoDelegate(SayHi); mydelegate(); void SayHi() { } Console.Writeline("Hiya!!") ;

Lambda výrazy (2/5) C# 2.0 nám dovolil tento zápis zjednodušit použitím anonymní metody. // kód z C# 2.0 class Program { } delegate void DemoDelegate(); static void Main(string[] args) { } DemoDelegate mydelegate = delegate() { }; Console.Writeline("Hiya!!"); mydelegate();

Lambda výrazy (3/5) Protože se často stává, že metody, které delegátem předáváme deklarujeme jen k jednomu jedinému použití, tudíž se nepotřebujeme dovolávat jejich jména, ušetří nám anonymní metody několik řádků kódu. V C# 3.0 máme jako další nadstavbu k dispozici lambda výrazy. Ty se zapisují jako seznam parametrů, symbol => a výraz či kód určující návratovou hodnotu daného lambda výrazu. // lambda výraz vracející bool který určuje, zda je číslo liché i => (i % d) == 0 Poznámka: Podobnost tohoto zápisu s funkcionálními jazyky jako Scheme nebo Lisp je více než zřejmá.

Lambda výrazy (4/5) S pomocí lambda výrazu přepíšeme předchozí kód takto: // kód z C# 3.0 class Program { delegate void DemoDelegate(); } static void Main(string[] args) { DemoDelegate mydelegate = () => Console.WriteLine("Hiya!!"); mydelegate(); }

Lambda výrazy (5/5) Z předchozího příkladu by se mohlo zdát že lambda výrazy jsou jen jakýmsi syntakticky odlišným zápisem anonymních metod, ale není tomu tak. Lambda výrazy tak, jak budou v novém C# uvedeny, mají větší funkcionalitu a jsou významově nadřazeny anonymním metodám. Mezi jejich zajímavé vlastnosti patří: lambda výrazy neudávají typy u vstupů ani výstupů můžou obsahovat buď dotazový výraz, nebo C# kód pomocí nového typu Expression lze lambda výraz zabalit a pracovat s ním jako s daty

Výrazové stromy okrajová pozámka Lambda výraz z předchozího příkladu můžeme vložit do výrazového stromu touto deklarací: Expression<DemoDelegate> filter = () => Console.WriteLine("Hiya!!") ; S tímto výrazovým stromem dále můžeme pracovat jako s datovým objektem a za chodu programu zkoumat a měnit jeho obsah (což bychom s klasickou funkcí pochopitelně nemohli).

LINQ LINQ = Language Integrated Query LINQ je převratné rozšíření jazyka C# (a VB 9.0), který má vést ke snadnému, přehlednému a objektovému (což je synonymum předešlých adjektiv ) propojení databáze a programu. Umožňuje přímo v jazyku C# psát konstrukce velice podobné jazyku SQL. Konstrukce z klíčových slov SELECT, WHERE, FROM a tak dále, psaných jen v trochu jiné syntaxi a ve zvláštně otočeném pořadí. Poznámka: LINQ je natolik komplexní a složitý nástroj, že informace zde uvedené lze brát jedině jako obšírný úvod doplněný několika příklady.

LINQ příklad DataContext db = new DataContext("server=.;initial catalog=northwind"); Table<Orders> orders = db.gettable<orders>(); Table<Customers> customers = db.gettable<customers>(); var q = from o in orders, c in customers where o.shipcity == "London" && (o.customerid == c.customerid) select new { o.orderdate, c.companyname, c.contacttitle, c.contactname }; foreach (var item in q) { Console.WriteLine("Order for {0} {1} at {2} placed on {3}", item.contacttitle, item.contactname, item.companyname, item.orderdate); }

Jak LINQ pracuje? Kód z předchozí strany je jakýmsi syntaktickým cukrem. Postupně se přes několik kroků přeloží do spleti volání funkcí, rozšiřujících funkcí a lambda výrazů, konkrétně předchozí kód se přeloží do (poněkud nepřehledného) tvaru: var q = QueryExtensions.SelectMany( QueryExtensions.Where(orders, o => o.shipcity == "London"), o => QueryExtensions.Select( QueryExtensions.Where(customers, c => o.customerid == c.customerid), c => new { o.orderdate, c.companyname, c.contacttitle, c.contactname }));

Je LINQ efektivní? Z tohoto zápisu se zdá, že první zavolání QueryExtensions.Where vyústí v dotaz na databázi, který vyselektuje údaje z tabulky orders, s Londýnem jako místem dodání, a QueryExtensions.SelectMany vyústí v iterování skrze tyto hodnoty, užívající mnohonásobný databázový dotaz na tabulku customer, a že tímto dojde k mnohonásobnemu joinu těchto tabulek na klientské straně aplikace. Naštěstí, LINQ je mnohem chytřejší. Kompiler využívá všechny základní postupy pro optimalizaci SQL dotazování, a tak, k velkému překvapení všech skeptiků, vytvoří jediný komplexní dotaz na databázi, kterým získá jen přesně určený výsek potřebných dat. Na internetu lze nalézt mnoho nezávislých článků, jejichž autoři testovali efektivnost demoverze LINQ, a panuje mezi nimi shoda, že alespoň v případě relativně jednoduchých dotazů, jejichž efektivitu je pro člověka snadné ověřit, funguje překlad LINQu velice efektivně.

Překvapivé vlastnosti LINQ Důsledky použití lambda výrazů: zpožděné vykonávání Ikdyž by deklarativní zápis dotazu (var lownumbers = ) mohl vést k opačnému pocitu, dotaz není v místě deklareace vykonán a jeho výsledek uložen do proměnné, nýbrž je do ní uložen sám dotaz. To se projevuje tím, že dokud se někde dále v kódu nedomáháme výstupu z dotazu, není dotaz vůbec proveden. Což může vést k tomu, že mezi dvěma dotazováními na stejný dotaz se změní hodnoty se kterými pracuje, a tudíž i jeho výstup. práce s kolekcemi Zatím jsme o LINQ mluvili pouze jako o nástroji na práci daty z databází. Jak ale víme, lambda výrazy jsou netypové a mohou sestávat z dotazů i konstrukcí běžný pro jazyk C#. Proto lze LINQ dotazy provádět nad jakýmikoliv kolekcemi s rozhraním IEnumerable. Navíc lze divoce kombinovat C# kód a LINQ konstrukce.

Příklad (1/2) práce s kolekcemi int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 }; var numbergroups = from n in numbers group n by n % 5 into g select new { Remainder = g.key, Numbers = g }; foreach (var g in numbergroups) { Console.WriteLine( Čísla se zbytkem {0} při dělění pěti:", g.remainder); foreach (var n in g.numbers) { Console.WriteLine(n); } }

Příklad (2/2) - zpožděné vykonání int[] numbers = new int[] { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 }; var lownumbers = from n in numbers where n <= 3 select n; Console.WriteLine( První volání <= 3:"); foreach (int n in lownumbers) Console.WriteLine(n); for (int i = 0; i < 10; i++) numbers[i] = -numbers[i]; // Druhé spuštění stejného dotazu bude iterovat nad změněnými daty // a vrátí jiný výsledek Console.WriteLine( Druhé volání <= 3:"); foreach (int n in lownumbers) Console.WriteLine(n);

Zdroje Microsoft.NET LINQ Preview (May 2006) http://www.codepost.org/ http://www.developer.com/ http://www.interact-sw.co.uk/

Mgr. David Keprt a Mgr. Aleš Keprt, Ph.D., 2006 Vytvořeno pro potřeby přednášky na UP Olomouc. Tento text není určen pro samostudium, ale jen jako vodítko pro přednášku, takže jeho obsah se může čtenáři zdát stručný, nekompletní či možná i chybný. Použití je povoleno jen na vlastní nebezpečí. V případě dalšího šíření tohoto dokumentu nebo i jeho kterékoliv části je NUTNO vždy uvést původního autora a odkaz na původní dokument. Komentáře můžete posílat emailem autorovi (adresu najdete pomocí Googlu). 26