Maybe it’s really just a sick thought, but who cares?! What is actually going to happen if one is enumerating an object which implements both an enumerator-interface and an implicit conversion to a type also implementing an enumerator-interface? At this time I actually know the answer (for Mono at least), but if we should reason about it, it’s almost given that it should use the direct implementation of the enumarator-interface and in that way avoid an implicit conversion.
Now it’s time to shower this post with some code (inspired by [1]):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | using System; using System.Collections; using System.Collections.Generic; namespace experiments { class MainClass { public static void Main(string[] args) { C<int> c = new C<int>(1, 2, 3, 4, 5); Console.WriteLine("IEnumerable<T>:"); foreach (int e in c) { Console.WriteLine(e); } Console.WriteLine(); Console.WriteLine("Implicit conversion to List<T>:"); foreach (int e in (List<int>)c) { Console.WriteLine(e); } Console.WriteLine(); Console.WriteLine("Implicit conversion to T[]:"); foreach (int e in (int[])c) { Console.WriteLine(e); } } } class C<T> : IEnumerable<T> { protected List<T> list; public C(params T[] elements) { this.list = new List<T>(); for (int i = 0; i < elements.Length; ++i) { this.list.Add(elements[i]); } } public IEnumerator<T> GetEnumerator() { for (int i = this.list.Count - 1; i >= 0; --i) { yield return this.list[i]; } } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } public static implicit operator List<T>(C<T> c) { return new List<T>(c.list); } public static implicit operator T[](C<T> c) { T[] arr = new T[c.list.Count]; if (c.list.Count > 0) { int j = 0; for (int i = c.list.Count / 2; i >= 0; --i) { arr[j++] = c.list[i]; } for (int i = (c.list.Count / 2) + 1; i < c.list.Count; ++i) { arr[j++] = c.list[i]; } } return arr; } } } |
And the result:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | IEnumerable<T>: 5 4 3 2 1 Implicit conversion to List<T>: 1 2 3 4 5 Implicit conversion to T[]: 3 2 1 4 5 |
..gets as expected – still a interesting test (in my opinion), though.
[1]: “C# Precisely” by Peter Sestoft and Henrik I. Hansen