{"id":3063,"date":"2010-05-20T05:13:00","date_gmt":"2010-05-20T05:13:00","guid":{"rendered":"https:\/\/test.simple-talk.com\/uncategorized\/why-enumerator-structs-are-a-really-bad-idea-redux\/"},"modified":"2016-07-28T10:50:00","modified_gmt":"2016-07-28T10:50:00","slug":"why-enumerator-structs-are-a-really-bad-idea-redux","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/blogs\/why-enumerator-structs-are-a-really-bad-idea-redux\/","title":{"rendered":"Why enumerator structs are a really bad idea (redux)"},"content":{"rendered":"<p>My <a href=\"https:\/\/www.simple-talk.com\/community\/blogs\/simonc\/archive\/2010\/05\/19\/91401.aspx\">previous blog post<\/a> went into some detail as to why calling <code>MoveNext<\/code> on a BCL generic collection enumerator didn&#8217;t quite do what you thought it would. This post covers the <code>Reset<\/code> method.<\/p>\n<p>To recap, here&#8217;s the simple wrapper around a linked list enumerator struct from my previous post (minus the <code>readonly<\/code> on the enumerator variable):<\/p>\n<pre>sealed class EnumeratorWrapper : IEnumerator&lt;int&gt; {\n\n    private LinkedList&lt;int&gt;.Enumerator m_Enumerator;\n\n    public EnumeratorWrapper(LinkedList&lt;int&gt; linkedList) {\n        m_Enumerator = linkedList.GetEnumerator();\n    }\n\n    public int Current {\n        get { return m_Enumerator.Current; }\n    }\n\n    object System.Collections.IEnumerator.Current {\n        get { return Current; }\n    }\n\n    public bool MoveNext() {\n        return m_Enumerator.MoveNext();\n    }\n\n    public void Reset() {\n        ((System.Collections.IEnumerator)m_Enumerator).Reset();\n    }\n\n    public void Dispose() {\n        m_Enumerator.Dispose();\n    }\n}<\/pre>\n<p>If you have a look at the <code>Reset<\/code> method, you&#8217;ll notice I&#8217;m having to cast to <code>IEnumerator<\/code> to be able to call <code>Reset<\/code> on <code>m_Enumerator<\/code>. This is because the implementation of <code>LinkedList&lt;int&gt;.Enumerator.Reset<\/code>, and indeed of all the other <code>Reset<\/code> methods on the BCL generic collection enumerators, is an explicit interface implementation.<\/p>\n<p>However, <code>IEnumerator<\/code> is a reference type. <code>LinkedList&lt;int&gt;.Enumerator<\/code> is a value type. That means, in order to call the reset method at all, the enumerator has to be boxed. And the IL confirms this: <\/p>\n<pre>.method public hidebysig newslot virtual final instance void Reset() cil managed\n{\n    .maxstack 8\n    L_0000: nop \n    L_0001: ldarg.0 \n    L_0002: ldfld valuetype \n        [System]System.Collections.Generic.LinkedList`1\/Enumerator&lt;int32&gt; \n            EnumeratorWrapper::m_Enumerator\n    L_0007: box \n        [System]System.Collections.Generic.LinkedList`1\/Enumerator&lt;int32&gt;\n    L_000c: callvirt instance void [mscorlib]System.Collections.IEnumerator::Reset()\n    L_0011: nop \n    L_0012: ret \n}<\/pre>\n<p>On line 0007, we&#8217;re doing a <code>box<\/code> operation, which copies the enumerator to a reference object on the heap, then on line 000c calling <code>Reset<\/code> on this boxed object. So <code>m_Enumerator<\/code> in the wrapper class is not modified by the call the <code>Reset<\/code>. And this is the <i>only<\/i> way to call the <code>Reset<\/code> method on this variable (without using reflection). <i>It is impossible to reset a BCL enumerator used as an unboxed value type<\/i>.<\/p>\n<p>Therefore, the only way that the collection enumerator struct can be used safely is to store them as a boxed <code>IEnumerator&lt;T&gt;<\/code>, and not use them as value types at all.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>My previous blog post went into some detail as to why calling MoveNext on a BCL generic collection enumerator didn&#8217;t quite do what you thought it would. This post covers the Reset method. To recap, here&#8217;s the simple wrapper around a linked list enumerator struct from my previous post (minus the readonly on the enumerator&#8230;&hellip;<\/p>\n","protected":false},"author":186659,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[2],"tags":[],"coauthors":[],"class_list":["post-3063","post","type-post","status-publish","format-standard","hentry","category-blogs"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/3063","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/186659"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=3063"}],"version-history":[{"count":1,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/3063\/revisions"}],"predecessor-version":[{"id":25031,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/3063\/revisions\/25031"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=3063"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=3063"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=3063"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=3063"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}