Advanced .NET Programming I 2nd Lecture Pavel Ježek pavel.jezek@d3s.mff.cuni.cz 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)
Iterator Methods Characteristics of an interator method class MyClass { string first = "first"; string second = "second"; string third = "third"; ... public IEnumerator<string> GetEnumerator() { yield return first; yield return second; yield return third; } Characteristics of an interator method has the signature public IEnumerator<T> GetEnumerator statement body contains at least one yield statement MyClass x = new MyClass(); ... foreach (string s in x) Console.Write(s + " "); // prints "first second third " returns a sequence of values foreach loop traverses this sequence How does an iterator method work? Note MyClass need not implement IEnumerable!
What Happens Behind the Scene? returns an object of the following class public IEnumerator<int> GetEnumerator() { try { ... } finally { } class _Enumerator1 : IEnumerator<int> { int Current { get {...} } bool MoveNext() {...} void Dispose() {...} } is translated into foreach (int x in list) Console.WriteLine(x); IEnumerator<int> _e = list.GetEnumerator(); try { while (_e.MoveNext()) Console.WriteLine(_e.Current); } finally { if (_e != null) _e.Dispose(); } MoveNext 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) { } public T Pop() { public IEnumerator<T> GetEnumerator() { for (int i = count - 1; i >= 0; --i) { yield return items[i]; } } class Stack<T>: IEnumerable<T> { ... public IEnumerator<T> GetEnumerator() { return new __Enumerator1(this); } class __Enumerator1: IEnumerator<T>, IEnumerator { int __state; T __current; Stack<T> __this; int i; ... public bool MoveNext() { switch (__state) { case 1: goto __state1; case 2: goto __state2; } i = __this.count - 1; __loop: if (i < 0) goto __state2; __current = __this.items[i]; __state = 1; return true; __state1: --i; goto __loop; __state2: __state = 2; return false; } } }
IEnumerable and IEnumerator (optimized) following statement: foreach (ElementType element in collection) statement; is translated into: var enumerator = collection.GetEnumerator(); try { ElementType element; while (enumerator.MoveNext()) { element = (ElementType) enumerator.Current; statement; } } finally { IDisposable disposable = enumerator as IDisposable; if (disposable != null) disposable.Dispose();
Iterating Over a Tree class Node { public Node left; public Node right; public 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, null, value) { public IEnumerator<int> GetEnumerator() { if (left != null) { foreach (int x in left) { yield return x; yield return value; if (right != null) { foreach (int x in right) { class Program { static void Main(string[] args) { Node root = new Node( new Node( new Node(2), new Node(7), 5 ), new Node( new Node(14), new Node(17), 15 ), new Node(25), 20 10 ); foreach (int x in root) { Console.Write("{0} ", x); } Console.WriteLine();
Iterating Over a Tree = “Counter-example” class Node { public Node left; public Node right; public 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, null, value) { public IEnumerator<int> GetEnumerator() { if (left != null) { foreach (int x in left) { yield return x; yield return value; if (right != null) { foreach (int x in right) { class Program { static void Main(string[] args) { Node root = new Node( new Node( new Node(2), new Node(7), 5 ), new Node( new Node(14), new Node(17), 15 ), new Node(25), 20 10 ); foreach (int x in root) { Console.Write("{0} ", x); } Console.WriteLine(); Generates new enumerator for each node in the tree!
Collection Classes .NET 1.0, 1.1 based on System.Object System.Collections namespace .NET 2.0, 3.0, 3.5, 4.0 generic classes System.Collections.Generic namespace
Interface ICollection : IEnumerable Interface ICollection<T> : IEnumerable, IEnumerable<T> Basic interface for collections: New in ICollection<T>: int Count { get; } number of elements bool IsSynchronized {get;} collection synchronised? object SyncRoot {get;} returns object for synchronisation void CopyTo(Array a, int index); copies the elements into array (starting at position index) void Add(T item); bool Remove(T item); void Clear(); bool Contains(T item;
Interface IList : ICollection, IEnumerable Interface IList<T> : ICollection<T>, IEnumerable, IEnumerable<T> Interface for object collections with a defined order interface IList { object this [ int index ] {get; set;} int Add(object value); void Insert(int index,object value); void Remove(object value); void RemoveAt(int index); void Clear(); bool Contains(object value); … }
Interface IDictionary Interface IDictionary<T, U> interface IDictionary : ICollection, IEnumerable { ICollection Keys {get;}; ICollection Values {get;}; object this[object key] {get; set;} void Add(object key, object value); void Remove(object key); bool Contains(object key); IDictionaryEnumerator GetEnumerator(); … } interface IDictionary<T, U> : IDictionary<TKey, TValue>, ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>, ... { public struct DictionaryEntry { public DictionaryEntry (object key, object value); public object Key {get;}; public object Value {get;}; }
Namespace System.Collections.Generic Classes List<T> SortedList<T, U> Dictionary<T, U> SortedDictionary<T, U> Stack<T> Queue<T> LinkedList<T> HashSet<T> SortedSet<T> implemented as a reallocated T[] (corresponds to ArrayList) implemented as a pair of realloc. T[], U[] (corr. to SortedList) implemented as a hash table in an array (corr. to Hashtable) implemented as a red-black tree implemented in a reallocated T[] (corresponds to Stack) implemented as a circular queue in r. T[] (corresponds to Queue) doubly linked list of LinkedListNode<T> (new in .NET 2.0) implemented as a hash table in an array + provides quick set operations (new in .NET 3.5 + implements ISet<T> in 4.0) implemented as a red-black tree (new in .NET 4.0) Interfaces ICollection<T> IList<T> IDictionary<T, U> ISet<T> IEnumerable<T> IEnumerator<T> IComparable<T> IComparer<T> IEquatable<T> IEqualityComparer<T> (new in .NET 4.0)
Type Variance
Any Meaningful Application of the Type Below? struct X<T> where T : class { private T t; public static implicit operator T(X<T> x) { return x.t; } public static implicit operator X<T>(T t) { X<T> x; x.t = t; return x;