Kordused/süklid

Tsükli nimiKonstruktsiooni tüüpTööpõhimõteMillal kasutadaSüntaksi eripäradTüüpilised vead ja riskidAllikas
forLoenduriga tsükkel (eeltingimus)Täidab koodiploki seni, kuni loogiline avaldis on tõene. Esmalt toimub initsialiseerimine, seejärel tingimuse kontroll, tsükli keha ja lõpuks iteraator.Kui teada on itereerimiste arv; elementide läbimiseks kogumites indeksite järgi; töö vahemike ja keeruka sammuloogikaga (nt iga kolmas element).Initsialiseerija, tingimus ja iteraatori osad on vabatahtlikud: for(;;) loob lõpmatu tsükli. Võimaldab kasutada unsafe-koodi massiividel pointeritega.Massiivi piire ületamine (IndexOutOfRangeException); lõpmatud tsüklid loendurivea tõttu; jõudluse langus, kui tingimuses kutsutakse sageli virtuaalseid omadusi (nt .Count).[1-4]
foreachIteratsioonitsükkel (iterator)Läbib kogumi elemente läbi IEnumerable liidese või GetEnumerator mustri. Muudetakse while-plokiks koos MoveNext() meetodi ja Current omaduse kasutusega.Kui vaja järjestikust ligipääsu kõigile kogumi elementidele ilma indeksita; asünkroonsete voogudega (await foreach).On “syntactic sugar”; itereerimismuutuja on ainult lugemiseks. Toetab duck-typingut (GetEnumerator olemasolu ilma selge liideseta).NullReferenceException null-kogumi läbimisel (eriti ?. operaatori puhul); mälu eraldamine virnas liidese kaudu; probleemid WeakReference’iga (GC eemaldab objekti kontrolli ja kasutuse vahel).[2, 3, 5, 6]
whileEeltingimusega tsükkelKontrollib loogilist tingimust enne iga iteratsiooni. Kui tingimus algselt vale, ei täideta tsükli keha kordagi.Kui itereerimiste arv ei ole eelnevalt teada, kuid määratud tingimusega (nt sisendi või sündmuse ootamine).Vajab ainult ühte loogilist avaldist sulgudes. Tihti kasutatakse lõpmatute tsüklite jaoks while(true).Lõpmatud tsüklid, kui tingimus ei muutu; ReDoS-risk stringi töötluses haavatavate regexitega.[1, 2, 4, 6]
do whileJäreltingimusega tsükkelEsmalt täidetakse tsükli keha, seejärel kontrollitakse tingimust. Tagab koodiploki vähemalt ühe täitmise.Kui tegevus peab toimuma vähemalt üks kord (nt andmete esmane päring enne valideerimist).Tingimuse lõpp peab olema semikooloniga: while (condition);Andmetüüpide üleujutus lõpmatu inkremendi korral; loogikavead, kui esimene täitmine on teatud sisendi puhul soovimatu.[1, 2, 4]

Õppejuhend: C# tsüklid ja LINQ

See juhend on mõeldud iteratsioonikonstruktsioonide, keele integreeritud päringute (LINQ) ja paralleelse andmetöötluse alaste teadmiste põhjalikuks ülevaateks ja süstematiseerimiseks .NET-keskkonnas, tuginedes esitatud materjalidele.

——————————————————————————–

Test oma teadmiste kontrollimiseks

Juhised: Vasta järgmistele küsimustele, kasutades antud allikatest pärit teavet. Iga vastus peaks koosnema 2-3 lausest.

  1. Mis on lõpmatu tsükkel ja millistes programmeerimisvaldkondades see kasulik olla saab?
  2. Mis on while ja do…while tsüklite põhimõtteline erinevus täitmisloogika seisukohast?
  3. Kuidas foreach tsükkel “kapoti all” töötab ja miks seda nimetatakse “süntaktiliseks suhkruks”?
  4. Mida mõeldakse LINQ kontekstis “edasilükatud täitmise” all?
  5. Defineerige LINQ-s “projektsiooni” mõistet ja kirjeldage anonüümsete tüüpide rolli selles protsessis.
  6. Nimetke vähemalt kolm viisi, kuidas C#-s pesastatud tsüklitest (nt topelt-for tsükkel) välja murda.
  7. Kuidas erinevad Parallel-klassi meetodid (nt Parallel.For) standardsetest C# tsüklitest?
  8. Miks võib IList-liidese kasutamine tsüklites negatiivselt mõjutada jõudlust võrreldes konkreetsete andmetüüpide kasutamisega?
  9. Milline on tingimusliku juurdepääsu operaatori (?.) kasutamise oht otse foreach-konstruktsioonis?
  10. Milleks kasutatakse LINQ-s koondfunktsioone ja kuidas nad kasutavad lambda-avaldisi?

——————————————————————————–

Vastused testile

  1. Lõpmatu tsükkel on tsükkel, mille väljumistingimus ei ole kunagi täidetud, mille tulemuseks on selle põhiosa pidev täitmine. Kuigi see on sageli vea tagajärg, on sellised tsüklid olulised operatsioonisüsteemide, mikrokontrolleriprogrammide ja rakenduste jaoks, mis ei tohiks iseenesest lõppeda.
  2. While tsükkel on eeltingimuslik tsükkel: loogiline avaldis hinnatakse enne põhiosa täitmist, seega ei pruugi see kunagi käivituda. Do…while tsükkel on järeltingimuslik tsükkel, mis garanteerib vähemalt ühe koodiploki täitmise, kuna tingimus hinnatakse iteratsiooni lõpus.
  3. Foreach tsükli teisendab kompilaator while konstruktsiooniks, mis kasutab loendurobjekti MoveNext() meetodite ja Current omadusega. Seda nimetatakse “süntaktiliseks suhkruks”, kuna see pakub lihtsamat ja loetavamat viisi kollektsioonide itereerimiseks, varjates iteraatoritega töötamise keerukat madala taseme loogikat.
  4. Edasilükatud täitmine tähendab, et LINQ päringut ei täideta selle defineerimise ajal; selle asemel luuakse iteraatorobjekt päringuloogika salvestamiseks. Tegelik andmete hankimine ja töötlemine toimub ainult tulemuste loetlemisel, näiteks foreach-tsükli käivitamisel või andmete sidumise meetodi kutsumisel.
  5. Projection on andmete teisendus päringu ajal, mis võimaldab teil eraldada ainult teatud objektide omadusi või muuta nende struktuuri. Anonüümseid tüüpe kasutatakse projektsioonides sageli ajutiste ümbrisobjektide loomiseks lennult ilma uut klassi formaalselt defineerimata.
  6. Pesastatud tsüklitest väljumiseks võite kasutada goto-lauset, mille silt määratakse vahetult pärast välimist tsüklit, või mähkida tsüklid meetodisse ja kasutada return-lauset. Teine levinud meetod on kasutada tõeväärtuslippu (tõeväärtusmuutujat), mida kontrollitakse iga tsükli tingimustes.
  7. Standardsed tsüklid täidetakse järjestikku ühel lõimel, samas kui Parallel-klassi meetodid on loodud iteratsioonide jaotamiseks mitme protsessori südamiku vahel. See võimaldab ülesandeid täita paralleelselt, kiirendades oluliselt suurte andmemahtude töötlemist mitmetuumalistes süsteemides.
  8. IList-liidese kasutamine aeglustab tsüklit, kuna igal iteratsioonil on vaja teha kalleid virtuaalseid meetodikõnesid (näiteks get_Count või get_Item). Lisaks võib foreachi puhul see viia loenduri kuhja eraldamiseni, mis tavalistes kollektsioonides (näiteks List) on pinupõhine struktuur.
  9. Kui kasutate foreachi (var x failis obj.prevCtx?.ioPendingRequests) ja prevCtx omadus on null, viskab programm NullReferenceExceptioni. See juhtub seetõttu, et operaator ? tagastab loendi allikana nullväärtuse ja foreachi konstruktsioon ei saa nullviitega töötada.
  10. Agregaatfunktsioone (Max, Min, Average, Count) kasutatakse andmerühmade arvutuste tegemiseks ja kokkuvõtlike tulemuste saamiseks. Nende funktsioonide lambda-avaldised võimaldavad teil määrata konkreetse objekti omaduse (nt p => p.UnitPrice), mis arvutusse kaasatakse.

——————————————————————————–

Essee teemad (aruteluküsimused)

  1. Arhitektuurilised kompromissid: LINQ objektideks vs. klassikalised Foreach-tsüklid. Analüüsige olukordi, kus LINQ deklaratiivne lähenemine on eelistatavam iteratiivsele loogikale, arvestades koodi loetavust ja jõudluse lisakulusid.
  2. Goto kasutamise probleem tänapäevases C# programmeerimises. Tuginedes kogukonna aruteludele (allikas 5), arutlege, kas sildile minek on vastuvõetav tööriist pesastatud tsüklitest väljumiseks või on see alati märk halvast disainist.
  3. .NET-i jõudluse areng: versioonide 6 ja versiooni 7 muudatuste analüüs. Mõelge, kuidas JIT-kompilaatori ja liidese implementatsioonide muudatused mõjutavad for- ja foreach-tsüklite jõudlust erinevates kollektsioonides.
  4. Iteratiivsete konstruktsioonide ohutus ja töökindlus. Arutage levinud programmeerimisvigu (allikas 9), näiteks WeakReferences’i vale käsitlemine tsüklites või kollektsioonide muutmise kõrvalmõjud läbimise ajal.
  5. Parallelism ja samaaegsus C#-s: millal saab Parallel.ForEach programmi aeglustada? Uurige tegureid, mis mõjutavad paralleelse töötlemise efektiivsust, sealhulgas lõimede haldamise lisakulusid ja lühikese tööajaga ülesandeid.

——————————————————————————–

Põhiterminite sõnastik

TerminMääratlus
LINQ (Language Integrated Query)C# keele laienduste komplekt, mis võimaldab kirjutada deklaratiivseid päringuid erinevate andmetüüpide (objektid, andmebaasid, XML) kohta otse koodis.
Anonüümne tüüp (Anonymous type)Andmetüüp, mille kompilaator loob automaatselt ajutiseks omaduste komplekti salvestamiseks ilma klassi eksplicitse deklaratsioonita.
Lambda-avaldis (Lambda expression)Anonüümne funktsioon, mida kasutatakse delegaatide või avaldisepuude loomiseks, kirjutatakse operaatori => abil.
Syntactic sugarKeelekonstruktsioonid, mis muudavad koodi inimese jaoks mugavamaks, kuid kompileerimisel asendatakse keerukamate, ekvivalentsete madalama taseme struktuuridega.
Enumerator (Peremeerija)Objekt, mis pakub liidest kogumi elementide järjestikuseks läbimiseks (sisaldab MoveNext, Current, Dispose).
IteratorMeetod või koodiplokk, mis samm-sammult tagastab väärtusi järjestusse, rakendades IEnumerable liidest.
Lazy loading (Hilinenud laadimine)Jõudluse optimeerimise tehnika, kus seotud andmed laaditakse alles siis, kui nende tegelikule kasutusele jõutakse.
TPL (Task Parallel Library).NET teek, mis lihtsustab paralleelsuse ja mitmetöötluse lisamist rakendustesse.
ReDoS (Regular Expression Denial of Service)Haavatavus, mis tekib ebaefektiivsete regulaaravaldiste kasutamisel ja võib põhjustada rakenduse külmumise teatud sisendstringide töötlemisel.
DataContextPeamine objekt LINQ to SQL-s, mis toimib vahendajana andmebaasi ja mälus olevate objektide vahel; haldab ühendusi ja muudatuste jälgimist.
Inkremendi operatsioon (postfix/prefix increment)Muutuja väärtuse suurendamine ühe võrra (i++ või ++i). Postfix vormis tagastatakse väärtus enne suurendamist, prefix vormis pärast.