Advanced NET Programming I 2 nd Lecture http

  • Slides: 10
Download presentation
Advanced. NET Programming I 2 nd Lecture http: //d 3 s. mff. cuni. cz/~jezek

Advanced. NET Programming I 2 nd Lecture http: //d 3 s. mff. cuni. cz/~jezek Pavel Ježek pavel. jezek@d 3 s. mff. cuni. cz CHARLES UNIVERSITY IN PRAGUE faculty of mathematics and physics Some of the slides are based on University of Linz. NET presentations. © University of Linz, Institute for System Software, 2004 published under the Microsoft Curriculum License (http: //www. msdnaa. net/curriculum/license_curriculum. aspx)

IEnumerable and IEnumerator following statement: foreach (Element. Type element in collection) statement; is translated

IEnumerable and IEnumerator following statement: foreach (Element. Type element in collection) statement; is translated into: IEnumerator enumerator = ((IEnumerable) collection). Get. Enumerator(); try { Element. Type element; while (enumerator. Move. Next()) { element = (Element. Type) enumerator. Current; statement; } } finally { IDisposable disposable = enumerator as IDisposable; if (disposable != null) disposable. Dispose(); }

IEnumerable and IEnumerator (optimized) following statement: foreach (Element. Type element in collection) statement; is

IEnumerable and IEnumerator (optimized) following statement: foreach (Element. Type element in collection) statement; is translated into: var enumerator = collection. Get. Enumerator(); try { Element. Type element; while (enumerator. Move. Next()) { element = (Element. Type) enumerator. Current; statement; } } finally { IDisposable disposable = enumerator as IDisposable; if (disposable != null) disposable. Dispose(); }

Iterators so far foreach loop can be applied to objects of classes which implement

Iterators so far foreach loop can be applied to objects of classes which implement IEnumerable class My. Class: IEnumerable<T> {. . . public IEnumerator<T> Get. Enumerator() { return new My. Enumerator(. . . ); } private class My. Enumerator: IEnumerator<string> { public string Current { get {. . . } } public bool Move. Next() {. . . } public void Reset() {. . . } } } My. Class x = new My. Class(); . . . foreach (string s in x). . . complicated to implement!! interface IEnumerable<T> { IEnumerator<T> Get. Enumerator(); }

Iterator Methods class My. Class { string first = "first"; string second = "second";

Iterator Methods class My. Class { string first = "first"; string second = "second"; string third = "third"; . . . public IEnumerator<string> Get. Enumerator() { yield return first; yield return second; yield return third; } } My. Class x = new My. Class(); . . . foreach (string s in x) Console. Write(s + " "); // prints "first second third " Note • My. Class need not implement IEnumerable! Characteristics of an interator method 1. has the signature public IEnumerator<T> Get. Enumerator 2. statement body contains at least one yield statement How does an iterator method work? 1. returns a sequence of values 2. foreach loop traverses this sequence

What Happens Behind the Scene? returns an object of the following class public IEnumerator<int>

What Happens Behind the Scene? returns an object of the following class public IEnumerator<int> Get. Enumerator() { try {. . . } finally {. . . } } class _Enumerator 1 : IEnumerator<int> { int Current { get {. . . } } bool Move. Next() {. . . } void Dispose() {. . . } } is translated into foreach (int x in list) Console. Write. Line(x); IEnumerator<int> _e = list. Get. Enumerator(); try { while (_e. Move. Next()) Console. Write. Line(_e. Current); } finally { if (_e != null) _e. Dispose(); } Move. Next runs to the next yield statement Dispose executes a possibly existing finally block in the iterator method

Implementation class Stack<T>: IEnumerable<T> { T[] items; int count; public void Push(T item) {

Implementation class Stack<T>: IEnumerable<T> { T[] items; int count; public void Push(T item) { } public T Pop() { } public IEnumerator<T> Get. Enumerator() { for (int i = count - 1; i >= 0; --i) { yield return items[i]; } } } class Stack<T>: IEnumerable<T> {. . . public IEnumerator<T> Get. Enumerator() { return new __Enumerator 1(this); } class __Enumerator 1: IEnumerator<T>, IEnumerator { int __state; T __current; Stack<T> __this; int i; . . . public bool Move. Next() { switch (__state) { case 1: goto __state 1; case 2: goto __state 2; } i = __this. count - 1; __loop: if (i < 0) goto __state 2; __current = __this. items[i]; __state = 1; return true; __state 1: --i; goto __loop; __state 2: __state = 2; return false; } } }

IEnumerable and IEnumerator (optimized) following statement: foreach (Element. Type element in collection) statement; is

IEnumerable and IEnumerator (optimized) following statement: foreach (Element. Type element in collection) statement; is translated into: var enumerator = collection. Get. Enumerator(); try { Element. Type element; while (enumerator. Move. Next()) { element = (Element. Type) enumerator. Current; statement; } } finally { IDisposable disposable = enumerator as IDisposable; if (disposable != null) disposable. Dispose(); }

Iterating Over a Tree class Node public : IEnumerable<int> { Node left; Node right;

Iterating Over a Tree class Node public : IEnumerable<int> { Node left; Node right; int value; public Node(Node left, Node right, int value) { this. left = left; this. right = right; this. value = value; } public Node(int value) : this(null, value) { } public IEnumerator<int> Get. Enumerator() { if (left != null) { foreach (int x in left) { yield return x; } } yield return value; if (right != null) { foreach (int x in right) { yield return x; } } class Program { static void Main(string[] args) { Node root = new Node(2), new Node(7), 5 ), new Node(14), new Node(17), 15 ), new Node(25), 20 ), 10 ); foreach (int x in root) { Console. Write("{0} ", x); } Console. Write. Line(); } }

Iterating Over a Tree = “Counter-example” class Node public : IEnumerable<int> { Node left;

Iterating Over a Tree = “Counter-example” class Node public : IEnumerable<int> { Node left; Node right; int value; public Node(Node left, Node right, int value) { this. left = left; this. right = right; this. value = value; } public Node(int value) : this(null, value) { } public IEnumerator<int> Get. Enumerator() { if (left != null) { foreach (int x in left) { yield return x; } } yield return value; if (right != null) { foreach (int x in right) { yield return x; } } class Program { static void Main(string[] args) { Node root = new Node(2), new Node(7), 5 ), new Node(14), new Node(17), 15 ), new Node(25), 20 ), 10 ); foreach (int x in root) { Console. Write("{0} ", x); } Console. Write. Line(); } } Generates new enumerator for each node in the tree!