1 / 25

Enumerable collection

Enumerable collection. int [] pins = { 9, 3, 7, 2 }; foreach ( int pin in pins) { Console.WriteLine (pin); } For each kolekcija se mo že primeniti samo na enumerable kolekcije – kolekcije koje implementiraju System.Collections.IEnumerable interface

keitha
Download Presentation

Enumerable collection

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Enumerable collection • int[] pins = { 9, 3, 7, 2 }; • foreach (int pin in pins) • { • Console.WriteLine(pin); • } • For each kolekcija se može primeniti samo na enumerable kolekcije – kolekcije koje implementiraju System.Collections.IEnumerable interface • System.Array classimplementiraIEnumerableinterface.

  2. IEnumerable interface • IEnumerableinterface deklariše samo jedan metod koji se naziva GetEnumerator • IEnumeratorGetEnumerator(); • GetEnumeratormethod vraća objekat koji implementira System.Collections.IEnumerator interface • Taj objekat se koristi za prolazak kroz elemente kolekcije • IEnumeratorinterface deklariše sledeća svojstva i metode: • object Current { get; } • boolMoveNext(); • void Reset();

  3. IEnumerator interface • Enumerator – objekat koji implementira IEnumerator interface se može zamisliti kao pokazivač koji pokazuje na elemente u listi. • Na početku, pokazuje ispred prvog elementa • Metod MoveNextpomera pokazivač za jedno mesto i vraća podatak tipa bool ako na sledećoj poziciji postoji element kolekcije, a false ako ga nema • Svojstvo Current se koristi za pristup elementima kolekcije – vraća objekat kolekcije • Metod Reset vraća pokazivač na početak liste – ispred prvog elementa

  4. For each - objašnjenje • For each struktura kreira enumerator pozivanjem metoda kolekcije GetEnumerator • Kroz elemente kolekcije se prolazi uzastopnim pozivanjem metoda MoveNext dok se ne dođe do kraja kolekcije • Metod Current omogućava pristup svakom elementu kolekcije kroz koju se prolazi • Za kreiranje korisničke klase kolekcije, neophodno je implementirati oba pomenuta interfejsa – IEnumerable u klasi kolekcije i enumerator u klasi pokazivača na elemente kolekcije

  5. Type safe IEnumerable i IEnumerator • Osim pomenutih interfejsa – IEnumerable i IEnumerate, postoje i type safe interfejsi IEnumerate<T> i IEnumerable<T> • IEnumerable<T> interfejs deklariše metod GetEnumeratorkoji vraća Enumerator<T>objekat • IEnumerator<T> interface deklariše svojstvo Current koje vraća objekat tipa T • Savetuje se upotreba upravo pomenutih generičkih interfejsa IEnumerable<T> i IEnumerate<T>

  6. Primer za korišćenje enumeratora • Za prethodnu generičku klasu Tree<T> kreiraće se klasa sa objektima enumeratorima koji će služiti za pristup elementima klase Tree preko For each konstrukcije • Za to će se konstruisati nova klasa TreeEnumerator koja implementira IEnumerator interfejs • Definicija / implementacija klase Tree se proširuje sa IEnumerable interfejsom i implementacijom • Klasa Program za testiranje se modifikuje tako što se umesto poziva metoda WalkTree koristi konstrukcija For each

  7. Mali trik u primeru • Da bi se stvari pojednostavile, primenjuje se sledeći trik: • Svi elementi binarnog drveta se u rastućem redosledu učitavaju u kolekciju Queue • Metod populate klase TreeEnumerator realizuje trik, tako što prolazi kroz sve elemente binarnog drveta u rastućem redosledu i ubacuje – Enqueue u kolekciju Queue • Struktura For each onda u stvari prolazi kroz elemente kolekcije Queue koji sadrže elemente binarnog drveta što je sakriveno od korisnika

  8. namespace BinaryTree • { • class TreeEnumerator<T> : IEnumerator<T> where T : IComparable<T> • { • public TreeEnumerator(Tree<T> data) • { • this.currentData = data; • } • private Tree<T> currentData = null; • private T currentItem = default(T); • private Queue<T> enumData = null;

  9. privatevoidpopulate(Queue<T> enumQueue, Tree<T> tree) • { • if (tree.LeftTree != null) • { • populate(enumQueue, tree.LeftTree); • } • enumQueue.Enqueue(tree.NodeData); • if (tree.RightTree != null) • { • populate(enumQueue, tree.RightTree); • } • }

  10. #region IEnumerator<T> Members • T IEnumerator<T>.Current • { • get • { • if (this.enumData == null) • throw new InvalidOperationException("Use MoveNext before calling Current"); • return this.currentItem; • } • } • #endregion

  11. boolSystem.Collections.IEnumerator.MoveNext() • { • if (this.enumData == null) • { • this.enumData = new Queue<T>(); • populate(this.enumData, this.currentData); • } • if (this.enumData.Count > 0) • { • this.currentItem = this.enumData.Dequeue(); • return true; • } • return false; • }

  12. IEnumerable<Titem> Interface • public class Tree<TItem> : IEnumerable<TItem> where TItem : IComparable<TItem> • { • #region IEnumerable<TItem> Members • IEnumerator<TItem> IEnumerable<TItem>.GetEnumerator() • { • return new TreeEnumerator<TItem>(this); • } • #endregion

  13. IEnumerable Interface • #region IEnumerable Members • System.Collections.IEnumeratorSystem.Collections.IEnumerable.GetEnumerator() • { • throw new NotImplementedException(); • } • #endregion • }

  14. class Program • { • static void Main(string[] args) • { • Tree<int> tree1 = new Tree<int>(10); • tree1.Insert(5); • tree1.Insert(11); • tree1.Insert(5); • tree1.Insert(-12); • tree1.Insert(15); • tree1.Insert(0); • tree1.Insert(14); • tree1.Insert(-8); • tree1.Insert(10); • foreach (int item in tree1) • Console.WriteLine(item); • } • }

  15. Enumerator preko Iterator-a • Iterator predstavlja blok koda koji se koristi za pojednostavljenje pristupa kolekciji • Kod iteratora u metodu GetEnumerator se koristi ključna reč yield koja se nalazi unutar tela ciklusa, i sasvim menja smisao ciklusa • Ključna reč yield označava da se radi o iteratoru • Svaki poziv iteratora – izaziva jedan prolazak kroz ciklus, tako da se kroz ciklus prođe tek kada se izređaju svi elementi • Stvarna implementacija je isto kao i bez iteratora, a kod generiše kompajler pri prevođenju • Pojednostavljenje se sastoji u tome da nije potrebna dodatna klasa za objekat enumeratora

  16. using System; • using System.Collections.Generic; • using System.Collections; • class BasicCollection<T> : IEnumerable<T> • { • private List<T> data = new List<T>(); • public void FillList(params T [] items) • { • foreach (var datum in items) • data.Add(datum); • }

  17. IEnumerator<T> IEnumerable<T>.GetEnumerator() • { • foreach (var datum in data) • yield return datum; • } • IEnumerator IEnumerable.GetEnumerator() • { • // Not implemented in this example • } • }

  18. BasicCollection<string> bc = new BasicCollection<string>(); • bc.FillList(“Twas”, “brillig”, “and”, “the”, “slithy”, “toves”); • foreach (string word in bc) • Console.WriteLine(word); • public IEnumerable<T> Reverse • { • get • { • for (int i = data.Count - 1; i >= 0; i--) • yield return data[i]; • } • }

  19. BasicCollection<string> bc = new BasicCollection<string>(); • bc.FillList(“Twas”, “brillig”, “and”, “the”, “slithy”, “toves”); • foreach (string word in bc.Reverse) • Console.WriteLine(word);

  20. Promena primera Tree za iterator • Primer sa klasom Tree se korišćenjem iteratora pojednostavljuje, tako da više nije potrebna dodatna klasa TreeEnumerator za enumerator • Implementacija za metod GetEnumerator()Ienumerable interfejsa se koriguje tako da se koristi yield što označava da se koristi iterator

  21. Promena primera Tree za iterator IEnumerator<TItem> IEnumerable<TItem>.GetEnumerator() { if (this.LeftTree != null) { foreach (TItem item in this.LeftTree) { yield return item; } } yield return this.NodeData; if (this.RightTree != null) { foreach (TItem item in this.RightTree) { yield return item; } } }

More Related