Linq päringukeel: Difference between revisions
Created page with 'LINQ Eesmärk Antud õpiobjekti eesmärgiks on tutvustada LINQ päringukeele olemust ning kasutamisvõimalusi C# programmeerimiskeeles. • LINQ päringukeelega seotud tehnoloogi…' |
|||
(19 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
LINQ | =LINQ päringukeelega seotud tehnoloogiad= | ||
LINQ päringukeele kasutamine on võimalik tänu mitmetele uutele tehnoloogiatele C# programmeerimiskeeles. Järgnevalt lühike ülevaade mõningatest nendest tehnoloogiatest. | |||
* Muutujatüüp var | |||
* Objekti initsialiseerijad | |||
* Anonüümsed muutujatüübid | |||
* Laiendusmeetodid | |||
* Lambda avaldised | |||
==Meetod ja päringulause LINQ== | |||
Jämedalt on võimalik LINQ kaheks jagada - päringulause ja meetodite LINQ. | |||
* Meetodite LINQ puhul järjestatakse enumereeritava objekti järgi meetodid, milles kasutatakse lambda avaldisi. | |||
* Päringulausete puhul kasutatakse SQL päringukeele sarnase süntaksiga päringukirjeldusi. | |||
Metoodika erinevuse ja mugavuse selgitamiseks loome XML'i, millele päringuid teha: | |||
<source lang="XML"> | |||
<?xml version="1.0" encoding="utf-8" ?> | |||
<house> | |||
<room id="1"> | |||
<computer id="1" OS="Windows" /> | |||
<computer id="2" OS="Linux" /> | |||
<computer id="3" OS="Linux" /> | |||
</room> | |||
<room id="2"> | |||
<computer id="4" OS="Windows" /> | |||
<computer id="5" OS="Windows" /> | |||
<computer id="6" OS="Linux" /> | |||
</room> | |||
<room id="3"> | |||
<computer id="7" OS="Windows" /> | |||
<computer id="8" OS="Windows" /> | |||
<computer id="9" OS="Linux" /> | |||
<computer id="10" OS="Windows" /> | |||
</room> | |||
</house> | |||
</source> | |||
Esmaks teeme päringu meetoditega sellesse XML'i pärime sealt välja kõik arvutid, mille operatsioonisüsteemiks on Linux: | |||
<source lang="CSharp"> | |||
var computers = XDocument.Load("house.xml") // Laeme XML'i failist | |||
.Root // Võtame juurelemendi, milleks on "house" element | |||
.Elements("room") // Saame juurelemendi kõik alamelemendid, mille nimi on "room" | |||
.SelectMany( // Me peame kasutama SelectMany funktsiooni, kuna meil on mitmedimensiooniline XML | |||
room => room.Elements("computer") // Vaatame järjest igas ruumis olevaid arvuteid | |||
.Where(computer => computer.Attribute("OS").Value == "Linux") // Tagastame vaid need, mis on Linuxiga | |||
); | |||
// Prindime välja kõik saadud elemendid | |||
foreach (var e in computers) | |||
Console.WriteLine(e.ToString()); | |||
</source> | |||
Nüüd sama asi LINQ päringulausena: | |||
<source lang="CSharp"> | |||
var computers = from XElement room in XDocument.Load("house.xml").Root.Elements("room") // Käime läbi XMLi juurelemendis olevad "room" elemendid | |||
from XElement computer in room.Elements("computer") // Igas ruumis käime läbi kõik "computer" elemendid | |||
where computer.Attribute("OS").Value == "Linux" // Filtreerime tagastatuks ainult need elemendid, millel on Linux | |||
select computer; // Valime, et tagastataks "computer" element | |||
// Prindime välja kõik saadud elemendid | |||
foreach (var e in computers) | |||
Console.WriteLine(e.ToString()); | |||
</source> | |||
Mõlema LINQ päringu tulemus on sama: | |||
<computer id="2" OS="Linux" /> | |||
<computer id="3" OS="Linux" /> | |||
<computer id="6" OS="Linux" /> | |||
<computer id="9" OS="Linux" /> | |||
Milles siis on vahe? Vahe on tegelikult ju loetavuses. Päringulausena on päring palju arusaadavam. Samas lihtsamate päringute puhul on jällegi mugavam kasutada meetodeid. | |||
==Muutujatüüp var== | |||
Muutujatüübiga var tähistatakse C# programmeerimiskeeles muutujaid, mille tüüp määratakse initsialiseerimise käigus. Samas on var tüübikindel, sest kui tüüp on korra määratud, siis edaspidi seda muuta ei ole võimalik. | |||
Näide | |||
<source lang="CSharp"> | |||
string sona = "tere"; // luuakse string tüüpi muutuja sona | |||
var sona2 = "tere"; // luuakse string tüüpi muutuja sona2 | |||
sona2 = 3 // tekib viga, sest püütakse string tüüpi muutujale omistada int tüüpi väärtus | |||
</source> | |||
==Objekti initsialiseerijad== | |||
Kui tavaliselt tuleb objekti loomise järel kõik vajalikud andmeväljad eraldi täita, siis objekti initsialiseerijad loovad võimaluse algväärtustada loomise käigus ka kõik vajalikud andmeväljad. | |||
Näide | |||
<source lang="CSharp">inime tonu = new inime(); // luuakse uus andmeobjekt tonu, mis on inime tüüpi | |||
tonu.eesnimi = "jaan"; // väärtustatakse andmeväli eesnimi stringiga „jaan“ | |||
tonu.vanus = 19; // väärtustatakse andmeväli vanus int tüüpi väärtusega 19 | |||
inime tonu2 = new inime { eesnimi = "jaan", vanus = 19 }; // on samaväärne eelnevaga | |||
</source> | |||
==Anonüümsed muutujatüübid== | |||
Anonüümsed muutujatüübid võimaldavad andmeobjekti tüübi luua selleks eelnevalt klassikirjeldust loomata. | |||
Näide | |||
<source lang="CSharp">var inime2 = new { eesnimi = "Heiki", vanus = 28 }; // luuakse kahe andmeväljaga uus muutujatüüp | |||
var jorss = new { vanus = 8, eesnimi = "Jaan" }; // luuakse kahe andmeväljaga uus muutujatüüp | |||
</source> | |||
Eelnevas näites toodud muutujatüübid on erinevad, sest nende andmeväljad on erinevas järjekorras (esimesel string ja int ning teisel int ja string). | |||
==Laiendusmeetodid== | |||
Laiendusmeetod on staatiline meetod, mis on väljakutsutav moel nagu see oleks konkreetse instantsi dünaamiline meetod. Võimalikuks teeb selle märksõna this meetodid parameetri ees. | |||
Kui luua uus klaas Laiendused ning sinna sisse meetod LoeSonadLauses, mis näib välja nii: | |||
<source lang="CSharp"> | |||
public static class Laiendused | |||
{ | |||
public static int LoeSonadLauses(this String lause) | |||
{ | |||
return lause.Split(new char[] { ' ', ',', '.' }).Length; | |||
} | |||
} | |||
</source> | |||
siis tekib kõigile samas nimeruumis olevatele stringidele kasutatavaks meetod LoeSonadLauses. Kui on soov kasutada stringidel teistes nimeruumides ka seda laiendusmeetodit, siis tuleb importida see klass vastavasse nimeruumi (kasutades using konstruktsiooni). | |||
Kui kasutada System.Linq nimeruumi, siis tekib muutujatüüpidele, mis realiseerivad IEnumerable tüüpi liidese laiendusmeetodid GroupBy, OrderBy, Average jne. | |||
==Lambda avaldised== | |||
Lambda avaldised C# keeles võimaldavad luua lihtsaid tingimuslauseid ning omistamisi. | |||
Näide | |||
<source lang="CSharp"> | |||
List<int> arvud = new List<int>(); // luuakse int tüüpi list | |||
for (int i = 0; i < 500; i++) | |||
arvud.Add(i); // täidetakse list arvudega 0..500 | |||
var paaritud = arvud.FindAll(N => N%2 != 0); // valitakse ainult paaritud arvud | |||
</source> | |||
Järgnevalt mõned lambda avaldiste kasutamise näited: | |||
<pre> | |||
Lambda avaldis Tulemus Vastuse tüüp | |||
x => x +1 Kui x = 1, siis tulemus on 2 int | |||
x => x == 5 Kui x = 5, siis vastus true, muul juhul false boolean | |||
x => x % 5 == 0 Kui x jagub viiega, siis true, muul juhul false boolean | |||
(x,y) => x+y x ja y summa int | |||
(x,y) => x== y Kui x ja y on võrdsed, siis true, muul juhul false boolean</pre> | |||
=LINQ päringud= | |||
LINQ päringud sarnanevad mõnevõrra SQL keele päringutele, kuid samas on need päringud rohkem sarnased keele üldisele süntaksile. | |||
Näide | |||
<source lang="CSharp">// loome lihtsa arvude listi, mis sisaldab arve nullist kuni 499’ni | |||
List<int> arvud = new List<int>(); // luuakse int tüüpi list | |||
for (int i = 0; i < 500; i++) | |||
arvud.Add(i); // täidetakse list arvudega 0..500 | |||
// teeme päringu, mis valiks sajast suuremad arvud: | |||
var paaritud2 = from x in arvud | |||
where x % 2 == 0 | |||
select x; | |||
</source> | |||
Eesti keeles võiks öelda, et üldiselt on LINQ päringu süntaks on järgmine: võta midagi kusagilt suuremast kuhjast, vaata, kas sobib, kui sobib, siis pista teise kuhja. | |||
Sorteerimine | |||
LINQ pärnig võimaldab ka tulemuste sorteerimist mingisuguste omaduste järgi. | |||
Näide | |||
<source lang="CSharp"> | |||
// Leia inimesed kelle nime pikkus on suurem kolmest ja sorteeri need vanuse järgi | |||
var inimesed3 = from x in inimesed | |||
where x.eesnimi.Length > 3 | |||
orderby x.vanus | |||
select x; | |||
</source> | |||
Samas on LINQ lauset võimalik kasutada ka ainult sorteerimiseks. | |||
Näide | |||
<source lang="CSharp"> | |||
// Leia inimesed ja sorteeri need vanuse järgi | |||
var inimesed3 = from x in inimesed | |||
orderby x.vanus | |||
select x; | |||
</source> | |||
Samuti on võimalik luua LINQ päring, kus sobivad elemendid sorteeritakse mintme erineva omaduse järgi ning kasutada vastupidist sorteerimisloogikat (alustades suurimast). | |||
<source lang="CSharp"> | |||
// Leia inimesed kelle nime pikkus on suurem kolmest ja sorteeri need vanuse ning nime järgi | |||
//vastupidises järjekorras | |||
var inimesed3 = from x in inimesed | |||
where x.eesnimi.Length > 3 | |||
orderby x.vanus, x.eesnimi descending | |||
select x; | |||
</source> | |||
===Iteratiivne vs deklaratiivne=== | |||
Kui LINQ ilmavalgust nägi, siis paljude arendajate jaoks oli see kui jumalik kingitus, kuna sai paljusid päringuid ülilihtsalt ja samas ka Lazy moodi teha. | |||
Järgmise näitega üritame selgitada, miks just kasutada LINQ-t. Mis on tema eelised iteratiivselt implementeeritud koodi puhul. | |||
Kõigepealt iteratiivne .NET 2.0 kood. Loome klassi kahe Employee klassi võrdlemiseks:[http://www.kodefuguru.com/post/2010/05/04/LINQ-is-Better-Than-ForEach.aspx] | |||
<source lang="CSharp"> | |||
public class EmployeeLastNameComparer : IComparer<Employee> | |||
{ | |||
public int Compare(Employee x, Employee y) | |||
{ | |||
return x.LastName.CompareTo(y.LastName); | |||
} | |||
} | |||
</source> | |||
Nüüd sorteerime .NET 2.0 stiilis:[http://www.kodefuguru.com/post/2010/05/04/LINQ-is-Better-Than-ForEach.aspx] | |||
<source lang="CSharp"> | |||
var employeeList = new List<Employee>(); | |||
employeeList.AddRange(employees); | |||
employeeList.Sort(new EmployeeLastNameComparer()); | |||
var names = new List<string>(); | |||
foreach (var employee in employeeList) | |||
{ | |||
if (employee.Role == Role.Developer) | |||
{ | |||
names.Add(employee.FullName); | |||
} | |||
} | |||
var developerNames = names.ToArray(); | |||
</source> | |||
Kuid sama asja saame ju LINQ'ga deklaratiivselt teha:[http://www.kodefuguru.com/post/2010/05/04/LINQ-is-Better-Than-ForEach.aspx] | |||
<source lang="CSharp"> | |||
var developerNames = employees.Where(e => e.Role == Role.Developer) | |||
.OrderBy(e => e.LastName) | |||
.Select(e => e.FullName) | |||
.ToArray(); | |||
</source> | |||
Tohutult vähem koodi! Ning mis on veel selle pluss? Loetavus ja vigade võimalus on väiksem! | |||
=LINQ to XML= | |||
LINQ to XML tehnoloogia sisaldab hulka tehnoloogiaid, mis on mõeldud XML formaadis info ja failide loomiseks, töötlemiseks ning muutmiseks. LINQ to XML vahendid on koondatud System.Xml.Linq nimeruumi. System.Xml.Linq nimeruum sisaldab mitmete klasside kirjeldusi, peamised klassid ja nende omavahelised seosed on kirjeldatud alloleval joonisel | |||
XDocument on andmetüüp, mis võimaldab mälus hoida koopiat XML dokumendist. XDocument võib sisaldada: XElement (juurelement, mida tohib olla ainult üks), Xdeclaration, XdocumentType ja XProcessingInstruction. | |||
XElement on andmetüüp, mis võimaldab mälus hoida koopiat XML elemendist. XDocument võib sisaldada: XElement (võib olla mitu), XComment, an XProcessingInstruction, XAttribute ja tekstilisi väärtuseid. | |||
XAttribute on andmetüüp, mis sisaldab nime ja väärtuse paari. | |||
Eelmainitud kolm andmetüüpi ongi põhilised, millega programmeerijal tuleb kokku puutuda. XML formaadis andmeid võib ette kujutada kui XElementidest koosnevat puud. | |||
XML objektide loomine | |||
XML objektidest kõige enam kasutatav on XElement. Uue XElemendi loomiseks saab kasutada XElemendi klassi konstruktoreid: | |||
XElement(XElement) Loob uue XElemendi olemasoleva XElemendi baasil | |||
XElement(XName) Loob uue XElemendi etteantud märgdendinimega | |||
XElement(XStreamingElement) Loob uue XElemendi olemasoleva XStreamingElement baasil | |||
XElement(XName, Object) Loob uue XElemendi etteantud märgdendinimega ning määrab elemendi sisuks etteanutd objekti | |||
XElement(XName, Object[]) Loob uue XElemendi etteantud märgdendinimega ning määrab elemendi sisuks etteanutd objektide massiivi | |||
Vaatame kõige lihtsamat juhtu: | |||
<source lang="CSharp"> | |||
//Loome uue XElemendi märgendinimega inimene | |||
XElement inimene = new XElement("inimene"); | |||
Console.WriteLine(inimene); | |||
// Väljund: <inimene /> | |||
</source> | |||
Loome nüüd XML objekti, mis sisaldab ka infot: | |||
<source lang="CSharp"> | |||
//Loome uue XElemendi märgendinimega inimene, | |||
//mis sisaldab väärtust "Jaan" | |||
XElement inimene2 = new XElement("inimene", "Jaan"); | |||
Console.WriteLine(inimene2); | |||
// Väljund: <inimene>Jaan</inimene> | |||
</source> | |||
Loome nüüd XML objekti, mis sisaldab teist XElementi: | |||
<source lang="CSharp"> | |||
//Loome uue XElemendi märgendinimega inimene, | |||
//mis sisaldab teist XElementi | |||
XElement inimene3 = new XElement("inimene", | |||
new XElement("nimi","Jaan")); | |||
Console.WriteLine(inimene3); | |||
// Väljund: | |||
//<inimene> | |||
// <nimi>Jaan</nimi> | |||
//</inimene> | |||
</source> | |||
Loome nüüd XML objekti, mis sisaldab kahte XElementi ja atribuuti: | |||
<source lang="CSharp"> | |||
//Loome uue XElemendi märgendinimega inimene, | |||
//mis sisaldab kahte XElementi ja atribuuti | |||
XElement inimene4 = new XElement("inimene", | |||
new XElement("eesNimi", "Jaan"), | |||
new XElement("pereNimi", "Igamees"), | |||
new XAttribute("id", 1)); | |||
Console.WriteLine(inimene4); | |||
// Väljund: | |||
//<inimene id="1"> | |||
// <eesNimi>Jaan</eesNimi> | |||
// <pereNimi>Igamees</pereNimi> | |||
//</inimene> | |||
</source> | |||
Eelnevaga samaväärne on järgnev näide: | |||
<source lang="CSharp"> | |||
//Loome uue XElemendi märgendinimega inimene, | |||
//mis sisaldab kahte XElementi ja atribuuti | |||
XElement inimene5 = new XElement("inimene"); | |||
inimene5.Add(new XElement("eesNimi", "Jaan")); | |||
inimene5.Add(new XElement("pereNimi", "Igamees")); | |||
inimene5.Add(new XAttribute("id", 1)); | |||
Console.WriteLine(inimene5); | |||
// Väljund: | |||
//<inimene id="1"> | |||
// <eesNimi>Jaan</eesNimi> | |||
// <pereNimi>Igamees</pereNimi> | |||
//</inimene> | |||
</source> | |||
==XML failidest lugemine ja nende muutmine== | |||
XML failist info lugemiseks kasutame näitena Eesti Panga poolt väljastatavaid valuutakursse. | |||
Eesti Pank pakub XML formaadis valuuta päevakursse aadressil : http://www.eestipank.ee/dynamic/erp/erp_xml.jsp?day=1&month=10&year=2009&type=4&lang=et, kusjuures antud aadressil on päevakursid 1. oktoober 2009 seisuga. | |||
Kui on soov saada mõne muu päeva päevakursse, siis peaks muutma aadressis sisalduvat kuupäeva. | |||
XML formaadis andmete mällu lugemiseks saab kasutada XElement või XDocument klassi meetodit Load. | |||
Näide: | |||
<source lang="CSharp"> | |||
//Loen Eesti panga poolt pakutavad päevakursid mällu | |||
XElement kursid = XElement.Load( | |||
"http://www.eestipank.ee/dynamic/erp/erp_xml.jsp?day=1&month=10&year=2009&type=4&lang=et"); | |||
//Trükin saadud XML formaadis andmed konsooli | |||
Console.WriteLine(kursid); | |||
// | |||
</source> | |||
Kui andmed on mällu loetud, siis on võimalik nende andmetega teostada LINQ päringuid. | |||
Näide: | |||
<source lang="CSharp"> | |||
//Teen päringu kurssidesse valides välja | |||
//"Body" nimelise elemendi alamelemendi "Currencies" | |||
// kõik alamelemendid | |||
var valuutaNimed = from x in kursid.Element("Body").Element("Currencies").Elements() | |||
select x.Attribute("text").Value; | |||
foreach (var x in valuutaNimed) | |||
Console.WriteLine(x); | |||
</source> | |||
Samuti on siinkohal võimalik seada kitsendusi, nii on näiteks võimalik otsida üles valuutad, mis sisaldavad nimes „kroon“. | |||
Näide: | |||
<source lang="CSharp"> | |||
//Teen päringu kurssidesse valides välja | |||
//"Body" nimelise elemendi alamelemendi "Currencies" | |||
// kõigi alamelementide atribuudi "text" väärtused, mis sisaldavad | |||
// "kroon" | |||
var kroonid = from x in kursid.Element("Body").Element("Currencies").Elements() | |||
where x.Attribute("text").Value.Contains("kroon") | |||
select x.Attribute("text").Value; | |||
foreach (var x in kroonid) | |||
Console.WriteLine(x); | |||
</source> | |||
Lisaks on alati võimalik kasutada sorteerimist: | |||
Näide: | |||
<source lang="CSharp"> | |||
//Teen päringu kurssidesse valides välja | |||
//"Body" nimelise elemendi alamelemendi "Currencies" | |||
// kõigi alamelementide atribuudid "text", mis sisaldavad | |||
// "kroon" ja sorteerin need pikkuse järgi | |||
var kroonid = from x in kursid.Element("Body").Element("Currencies").Elements() | |||
where x.Attribute("text").Value.Contains("kroon") | |||
orderby x.Attribute("text").Value.Length | |||
select x.Attribute("text"); | |||
foreach (var x in kroonid) | |||
Console.WriteLine(x.Value); | |||
</source> | |||
Kui nüüd muuta mõnda päringuga saadud väärtust, näiteks asendada saadud kroonide väärtuses „kroon“ sõnaga „euro“ siis muutuvad ka nende elementdide ja atribuutide väärtused algses Xelemendis! | |||
Näide: | |||
<source lang="CSharp"> | |||
// Asendan väärtuse "kroon" väärtusega "euro" | |||
foreach (var x in kroonid) | |||
x.Value = x.Value.Replace("kroon", "euro"); | |||
//Trükin välja mälus oleva XElemendi "kursid" | |||
Console.WriteLine(kursid); | |||
</source> | |||
Muudetud XElement on lihtsalt salvestatav, selleks tuleb kasutada meetodit Save. | |||
NB! Kui anda meetodile ette lihtsalt failinimi, siis salvestatakse fail programmi töökataloogi | |||
Näide: | |||
<source lang="CSharp"> | |||
//Salvestan XElement kursid faili nimega kursid_muudetud.xml | |||
kursid.Save("kursid_muudetud.xml"); | |||
</source> |
Latest revision as of 00:07, 16 February 2012
LINQ päringukeelega seotud tehnoloogiad
LINQ päringukeele kasutamine on võimalik tänu mitmetele uutele tehnoloogiatele C# programmeerimiskeeles. Järgnevalt lühike ülevaade mõningatest nendest tehnoloogiatest.
- Muutujatüüp var
- Objekti initsialiseerijad
- Anonüümsed muutujatüübid
- Laiendusmeetodid
- Lambda avaldised
Meetod ja päringulause LINQ
Jämedalt on võimalik LINQ kaheks jagada - päringulause ja meetodite LINQ.
- Meetodite LINQ puhul järjestatakse enumereeritava objekti järgi meetodid, milles kasutatakse lambda avaldisi.
- Päringulausete puhul kasutatakse SQL päringukeele sarnase süntaksiga päringukirjeldusi.
Metoodika erinevuse ja mugavuse selgitamiseks loome XML'i, millele päringuid teha:
<?xml version="1.0" encoding="utf-8" ?>
<house>
<room id="1">
<computer id="1" OS="Windows" />
<computer id="2" OS="Linux" />
<computer id="3" OS="Linux" />
</room>
<room id="2">
<computer id="4" OS="Windows" />
<computer id="5" OS="Windows" />
<computer id="6" OS="Linux" />
</room>
<room id="3">
<computer id="7" OS="Windows" />
<computer id="8" OS="Windows" />
<computer id="9" OS="Linux" />
<computer id="10" OS="Windows" />
</room>
</house>
Esmaks teeme päringu meetoditega sellesse XML'i pärime sealt välja kõik arvutid, mille operatsioonisüsteemiks on Linux:
var computers = XDocument.Load("house.xml") // Laeme XML'i failist
.Root // Võtame juurelemendi, milleks on "house" element
.Elements("room") // Saame juurelemendi kõik alamelemendid, mille nimi on "room"
.SelectMany( // Me peame kasutama SelectMany funktsiooni, kuna meil on mitmedimensiooniline XML
room => room.Elements("computer") // Vaatame järjest igas ruumis olevaid arvuteid
.Where(computer => computer.Attribute("OS").Value == "Linux") // Tagastame vaid need, mis on Linuxiga
);
// Prindime välja kõik saadud elemendid
foreach (var e in computers)
Console.WriteLine(e.ToString());
Nüüd sama asi LINQ päringulausena:
var computers = from XElement room in XDocument.Load("house.xml").Root.Elements("room") // Käime läbi XMLi juurelemendis olevad "room" elemendid
from XElement computer in room.Elements("computer") // Igas ruumis käime läbi kõik "computer" elemendid
where computer.Attribute("OS").Value == "Linux" // Filtreerime tagastatuks ainult need elemendid, millel on Linux
select computer; // Valime, et tagastataks "computer" element
// Prindime välja kõik saadud elemendid
foreach (var e in computers)
Console.WriteLine(e.ToString());
Mõlema LINQ päringu tulemus on sama:
<computer id="2" OS="Linux" /> <computer id="3" OS="Linux" /> <computer id="6" OS="Linux" /> <computer id="9" OS="Linux" />
Milles siis on vahe? Vahe on tegelikult ju loetavuses. Päringulausena on päring palju arusaadavam. Samas lihtsamate päringute puhul on jällegi mugavam kasutada meetodeid.
Muutujatüüp var
Muutujatüübiga var tähistatakse C# programmeerimiskeeles muutujaid, mille tüüp määratakse initsialiseerimise käigus. Samas on var tüübikindel, sest kui tüüp on korra määratud, siis edaspidi seda muuta ei ole võimalik.
Näide
string sona = "tere"; // luuakse string tüüpi muutuja sona
var sona2 = "tere"; // luuakse string tüüpi muutuja sona2
sona2 = 3 // tekib viga, sest püütakse string tüüpi muutujale omistada int tüüpi väärtus
Objekti initsialiseerijad
Kui tavaliselt tuleb objekti loomise järel kõik vajalikud andmeväljad eraldi täita, siis objekti initsialiseerijad loovad võimaluse algväärtustada loomise käigus ka kõik vajalikud andmeväljad.
Näide
inime tonu = new inime(); // luuakse uus andmeobjekt tonu, mis on inime tüüpi
tonu.eesnimi = "jaan"; // väärtustatakse andmeväli eesnimi stringiga „jaan“
tonu.vanus = 19; // väärtustatakse andmeväli vanus int tüüpi väärtusega 19
inime tonu2 = new inime { eesnimi = "jaan", vanus = 19 }; // on samaväärne eelnevaga
Anonüümsed muutujatüübid
Anonüümsed muutujatüübid võimaldavad andmeobjekti tüübi luua selleks eelnevalt klassikirjeldust loomata.
Näide
var inime2 = new { eesnimi = "Heiki", vanus = 28 }; // luuakse kahe andmeväljaga uus muutujatüüp
var jorss = new { vanus = 8, eesnimi = "Jaan" }; // luuakse kahe andmeväljaga uus muutujatüüp
Eelnevas näites toodud muutujatüübid on erinevad, sest nende andmeväljad on erinevas järjekorras (esimesel string ja int ning teisel int ja string).
Laiendusmeetodid
Laiendusmeetod on staatiline meetod, mis on väljakutsutav moel nagu see oleks konkreetse instantsi dünaamiline meetod. Võimalikuks teeb selle märksõna this meetodid parameetri ees. Kui luua uus klaas Laiendused ning sinna sisse meetod LoeSonadLauses, mis näib välja nii:
public static class Laiendused
{
public static int LoeSonadLauses(this String lause)
{
return lause.Split(new char[] { ' ', ',', '.' }).Length;
}
}
siis tekib kõigile samas nimeruumis olevatele stringidele kasutatavaks meetod LoeSonadLauses. Kui on soov kasutada stringidel teistes nimeruumides ka seda laiendusmeetodit, siis tuleb importida see klass vastavasse nimeruumi (kasutades using konstruktsiooni). Kui kasutada System.Linq nimeruumi, siis tekib muutujatüüpidele, mis realiseerivad IEnumerable tüüpi liidese laiendusmeetodid GroupBy, OrderBy, Average jne.
Lambda avaldised
Lambda avaldised C# keeles võimaldavad luua lihtsaid tingimuslauseid ning omistamisi.
Näide
List<int> arvud = new List<int>(); // luuakse int tüüpi list
for (int i = 0; i < 500; i++)
arvud.Add(i); // täidetakse list arvudega 0..500
var paaritud = arvud.FindAll(N => N%2 != 0); // valitakse ainult paaritud arvud
Järgnevalt mõned lambda avaldiste kasutamise näited:
Lambda avaldis Tulemus Vastuse tüüp x => x +1 Kui x = 1, siis tulemus on 2 int x => x == 5 Kui x = 5, siis vastus true, muul juhul false boolean x => x % 5 == 0 Kui x jagub viiega, siis true, muul juhul false boolean (x,y) => x+y x ja y summa int (x,y) => x== y Kui x ja y on võrdsed, siis true, muul juhul false boolean
LINQ päringud
LINQ päringud sarnanevad mõnevõrra SQL keele päringutele, kuid samas on need päringud rohkem sarnased keele üldisele süntaksile.
Näide
// loome lihtsa arvude listi, mis sisaldab arve nullist kuni 499’ni
List<int> arvud = new List<int>(); // luuakse int tüüpi list
for (int i = 0; i < 500; i++)
arvud.Add(i); // täidetakse list arvudega 0..500
// teeme päringu, mis valiks sajast suuremad arvud:
var paaritud2 = from x in arvud
where x % 2 == 0
select x;
Eesti keeles võiks öelda, et üldiselt on LINQ päringu süntaks on järgmine: võta midagi kusagilt suuremast kuhjast, vaata, kas sobib, kui sobib, siis pista teise kuhja. Sorteerimine LINQ pärnig võimaldab ka tulemuste sorteerimist mingisuguste omaduste järgi.
Näide
// Leia inimesed kelle nime pikkus on suurem kolmest ja sorteeri need vanuse järgi
var inimesed3 = from x in inimesed
where x.eesnimi.Length > 3
orderby x.vanus
select x;
Samas on LINQ lauset võimalik kasutada ka ainult sorteerimiseks.
Näide
// Leia inimesed ja sorteeri need vanuse järgi
var inimesed3 = from x in inimesed
orderby x.vanus
select x;
Samuti on võimalik luua LINQ päring, kus sobivad elemendid sorteeritakse mintme erineva omaduse järgi ning kasutada vastupidist sorteerimisloogikat (alustades suurimast).
// Leia inimesed kelle nime pikkus on suurem kolmest ja sorteeri need vanuse ning nime järgi
//vastupidises järjekorras
var inimesed3 = from x in inimesed
where x.eesnimi.Length > 3
orderby x.vanus, x.eesnimi descending
select x;
Iteratiivne vs deklaratiivne
Kui LINQ ilmavalgust nägi, siis paljude arendajate jaoks oli see kui jumalik kingitus, kuna sai paljusid päringuid ülilihtsalt ja samas ka Lazy moodi teha.
Järgmise näitega üritame selgitada, miks just kasutada LINQ-t. Mis on tema eelised iteratiivselt implementeeritud koodi puhul.
Kõigepealt iteratiivne .NET 2.0 kood. Loome klassi kahe Employee klassi võrdlemiseks:[1]
public class EmployeeLastNameComparer : IComparer<Employee>
{
public int Compare(Employee x, Employee y)
{
return x.LastName.CompareTo(y.LastName);
}
}
Nüüd sorteerime .NET 2.0 stiilis:[2]
var employeeList = new List<Employee>();
employeeList.AddRange(employees);
employeeList.Sort(new EmployeeLastNameComparer());
var names = new List<string>();
foreach (var employee in employeeList)
{
if (employee.Role == Role.Developer)
{
names.Add(employee.FullName);
}
}
var developerNames = names.ToArray();
Kuid sama asja saame ju LINQ'ga deklaratiivselt teha:[3]
var developerNames = employees.Where(e => e.Role == Role.Developer)
.OrderBy(e => e.LastName)
.Select(e => e.FullName)
.ToArray();
Tohutult vähem koodi! Ning mis on veel selle pluss? Loetavus ja vigade võimalus on väiksem!
LINQ to XML
LINQ to XML tehnoloogia sisaldab hulka tehnoloogiaid, mis on mõeldud XML formaadis info ja failide loomiseks, töötlemiseks ning muutmiseks. LINQ to XML vahendid on koondatud System.Xml.Linq nimeruumi. System.Xml.Linq nimeruum sisaldab mitmete klasside kirjeldusi, peamised klassid ja nende omavahelised seosed on kirjeldatud alloleval joonisel
XDocument on andmetüüp, mis võimaldab mälus hoida koopiat XML dokumendist. XDocument võib sisaldada: XElement (juurelement, mida tohib olla ainult üks), Xdeclaration, XdocumentType ja XProcessingInstruction.
XElement on andmetüüp, mis võimaldab mälus hoida koopiat XML elemendist. XDocument võib sisaldada: XElement (võib olla mitu), XComment, an XProcessingInstruction, XAttribute ja tekstilisi väärtuseid.
XAttribute on andmetüüp, mis sisaldab nime ja väärtuse paari.
Eelmainitud kolm andmetüüpi ongi põhilised, millega programmeerijal tuleb kokku puutuda. XML formaadis andmeid võib ette kujutada kui XElementidest koosnevat puud.
XML objektide loomine XML objektidest kõige enam kasutatav on XElement. Uue XElemendi loomiseks saab kasutada XElemendi klassi konstruktoreid:
XElement(XElement) Loob uue XElemendi olemasoleva XElemendi baasil XElement(XName) Loob uue XElemendi etteantud märgdendinimega XElement(XStreamingElement) Loob uue XElemendi olemasoleva XStreamingElement baasil XElement(XName, Object) Loob uue XElemendi etteantud märgdendinimega ning määrab elemendi sisuks etteanutd objekti XElement(XName, Object[]) Loob uue XElemendi etteantud märgdendinimega ning määrab elemendi sisuks etteanutd objektide massiivi
Vaatame kõige lihtsamat juhtu:
//Loome uue XElemendi märgendinimega inimene
XElement inimene = new XElement("inimene");
Console.WriteLine(inimene);
// Väljund: <inimene />
Loome nüüd XML objekti, mis sisaldab ka infot:
//Loome uue XElemendi märgendinimega inimene,
//mis sisaldab väärtust "Jaan"
XElement inimene2 = new XElement("inimene", "Jaan");
Console.WriteLine(inimene2);
// Väljund: <inimene>Jaan</inimene>
Loome nüüd XML objekti, mis sisaldab teist XElementi:
//Loome uue XElemendi märgendinimega inimene,
//mis sisaldab teist XElementi
XElement inimene3 = new XElement("inimene",
new XElement("nimi","Jaan"));
Console.WriteLine(inimene3);
// Väljund:
//<inimene>
// <nimi>Jaan</nimi>
//</inimene>
Loome nüüd XML objekti, mis sisaldab kahte XElementi ja atribuuti:
//Loome uue XElemendi märgendinimega inimene,
//mis sisaldab kahte XElementi ja atribuuti
XElement inimene4 = new XElement("inimene",
new XElement("eesNimi", "Jaan"),
new XElement("pereNimi", "Igamees"),
new XAttribute("id", 1));
Console.WriteLine(inimene4);
// Väljund:
//<inimene id="1">
// <eesNimi>Jaan</eesNimi>
// <pereNimi>Igamees</pereNimi>
//</inimene>
Eelnevaga samaväärne on järgnev näide:
//Loome uue XElemendi märgendinimega inimene,
//mis sisaldab kahte XElementi ja atribuuti
XElement inimene5 = new XElement("inimene");
inimene5.Add(new XElement("eesNimi", "Jaan"));
inimene5.Add(new XElement("pereNimi", "Igamees"));
inimene5.Add(new XAttribute("id", 1));
Console.WriteLine(inimene5);
// Väljund:
//<inimene id="1">
// <eesNimi>Jaan</eesNimi>
// <pereNimi>Igamees</pereNimi>
//</inimene>
XML failidest lugemine ja nende muutmine
XML failist info lugemiseks kasutame näitena Eesti Panga poolt väljastatavaid valuutakursse.
Eesti Pank pakub XML formaadis valuuta päevakursse aadressil : http://www.eestipank.ee/dynamic/erp/erp_xml.jsp?day=1&month=10&year=2009&type=4&lang=et, kusjuures antud aadressil on päevakursid 1. oktoober 2009 seisuga. Kui on soov saada mõne muu päeva päevakursse, siis peaks muutma aadressis sisalduvat kuupäeva.
XML formaadis andmete mällu lugemiseks saab kasutada XElement või XDocument klassi meetodit Load.
Näide:
//Loen Eesti panga poolt pakutavad päevakursid mällu
XElement kursid = XElement.Load(
"http://www.eestipank.ee/dynamic/erp/erp_xml.jsp?day=1&month=10&year=2009&type=4&lang=et");
//Trükin saadud XML formaadis andmed konsooli
Console.WriteLine(kursid);
//
Kui andmed on mällu loetud, siis on võimalik nende andmetega teostada LINQ päringuid. Näide:
//Teen päringu kurssidesse valides välja
//"Body" nimelise elemendi alamelemendi "Currencies"
// kõik alamelemendid
var valuutaNimed = from x in kursid.Element("Body").Element("Currencies").Elements()
select x.Attribute("text").Value;
foreach (var x in valuutaNimed)
Console.WriteLine(x);
Samuti on siinkohal võimalik seada kitsendusi, nii on näiteks võimalik otsida üles valuutad, mis sisaldavad nimes „kroon“.
Näide:
//Teen päringu kurssidesse valides välja
//"Body" nimelise elemendi alamelemendi "Currencies"
// kõigi alamelementide atribuudi "text" väärtused, mis sisaldavad
// "kroon"
var kroonid = from x in kursid.Element("Body").Element("Currencies").Elements()
where x.Attribute("text").Value.Contains("kroon")
select x.Attribute("text").Value;
foreach (var x in kroonid)
Console.WriteLine(x);
Lisaks on alati võimalik kasutada sorteerimist:
Näide:
//Teen päringu kurssidesse valides välja
//"Body" nimelise elemendi alamelemendi "Currencies"
// kõigi alamelementide atribuudid "text", mis sisaldavad
// "kroon" ja sorteerin need pikkuse järgi
var kroonid = from x in kursid.Element("Body").Element("Currencies").Elements()
where x.Attribute("text").Value.Contains("kroon")
orderby x.Attribute("text").Value.Length
select x.Attribute("text");
foreach (var x in kroonid)
Console.WriteLine(x.Value);
Kui nüüd muuta mõnda päringuga saadud väärtust, näiteks asendada saadud kroonide väärtuses „kroon“ sõnaga „euro“ siis muutuvad ka nende elementdide ja atribuutide väärtused algses Xelemendis!
Näide:
// Asendan väärtuse "kroon" väärtusega "euro"
foreach (var x in kroonid)
x.Value = x.Value.Replace("kroon", "euro");
//Trükin välja mälus oleva XElemendi "kursid"
Console.WriteLine(kursid);
Muudetud XElement on lihtsalt salvestatav, selleks tuleb kasutada meetodit Save. NB! Kui anda meetodile ette lihtsalt failinimi, siis salvestatakse fail programmi töökataloogi
Näide:
//Salvestan XElement kursid faili nimega kursid_muudetud.xml
kursid.Save("kursid_muudetud.xml");