title: How does foreach call GetEnumerator()? Via IEnumerable reference or via...?
body: <pre><code>    static void Main(string[] args)
      {
          List&lt;int&gt; listArray = new List&lt;int&gt;();
          listArray.Add(100);
          foreach (int item in listArray)
              Console.WriteLine(item);
      }
  </code></pre>
  
  <p>a) When <code>foreach</code> statement calls <code>listArray's IEnumerable&lt;int&gt;.GetEnumerator()</code> implementation, does it call it via <code>listArray.GetEnumerator()</code> or <code>IEnumerable&lt;int&gt;.GetEnumerator()</code> or  <code>IEnumerable.GetEnumerator()</code> ?</p>
  
  <p>b) Similarly, when <code>foreach</code> references object returned by <code>listArray's IEnumerable&lt;int&gt;.GetEnumerator()</code>, does it reference this object via <code>IEnumerator</code> or <code>IEnumerator&lt;int&gt;</code> reference type?</p>
  
  <p>thank you</p>
  
  <p><strong>EDIT:</strong></p>
  
  <p>Some of my questions will quote this text:</p>
  
  <blockquote>
    <p>o Perform member lookup on the type X
    with identifier GetEnumerator and no
    type arguments. If the member lookup
    does not produce a match, or it
    produces an ambiguity, or produces a
    match that is not a method group,
    check for an enumerable interface as
    described below. It is recommended
    that a warning be issued if member
    lookup produces anything except a
    method group or no match.</p>
    
    <p>o Perform overload resolution using
    the resulting method group and an
    empty argument list. If overload
    resolution results in no applicable
    methods, results in an ambiguity, or
    results in a single best method but
    that method is either static or not
    public, check for an enumerable
    interface as described below. It is
    recommended that a warning be issued
    if overload resolution produces
    anything except an unambiguous public
    instance method or no applicable
    methods.</p>
    
    <p>o If the return type E of the
    GetEnumerator method is not a class,
    struct or interface type, an error is
    produced and no further steps are
    taken.</p>
    
    <p>o Member lookup is performed on E
    with the identifier Current and no
    type arguments. If the member lookup
    produces no match, the result is an
    error, or the result is anything
    except a public instance property that
    permits reading, an error is produced
    and no further steps are taken.</p>
    
    <p>o Member lookup is performed on E with
    the identifier MoveNext and no type
    arguments. If the member lookup
    produces no match, the result is an
    error, or the result is anything
    except a method group, an error is
    produced and no further steps are
    taken.</p>
    
    <p>o Overload resolution is performed on
    the method group with an empty
    argument list. If overload resolution
    results in no applicable methods,
    results in an ambiguity, or results in
    a single best method but that method
    is either static or not public, or its
    return type is not bool, an error is
    produced and no further steps are
    taken.</p>
    
    <p>o The collection type is X, the
    enumerator type is E, and the element
    type is the type of the Current
    property. </p>
    
    <ul>
    <li><p>Otherwise, check for an enumerable interface:
          o If there is exactly one type T such that there is an implicit
    conversion from X to the interface
    System.Collections.Generic.IEnumerable,
    then the collection type is this
    interface, the enumerator type is the
    interface
    System.Collections.Generic.IEnumerator,
    and the element type is T.</p></li>
    <li><p>Otherwise, if there is more than one such type T, then an
    error is produced and no further steps
    are taken.</p></li>
    <li><p>Otherwise, if there is an implicit conversion from X to the
    System.Collections.IEnumerable
    interface, then the collection type is
    this interface, the enumerator type is
    the interface
    System.Collections.IEnumerator, and
    the element type is object.</p></li>
    <li><p>Otherwise, an error is produced and no further steps are
    taken.</p></li>
    </ul>
  </blockquote>
  
  <p>1) </p>
  
  <p>Quote from Eric Lippert:</p>
  
  <blockquote>
    <p>Option (1) is correct. Note that this
    means that the enumerator returned is
    an unboxed mutable struct.</p>
    
    <p>The fact that this is a mutable struct
    has very real effects if you do
    something foolish like passing around
    the struct as though it were a
    reference type; it will be copied by
    value, not by reference.</p>
  </blockquote>
  
  <p>From <a href="http://en.csharp-online.net/ECMA-334:_15.8.4_The_foreach_statement" rel="noreferrer">http://en.csharp-online.net/ECMA-334:_15.8.4_The_foreach_statement</a> :</p>
  
  <blockquote>
    <p>foreach (V v in x) embedded-statement </p>
    
    <p>is then expanded to: </p>
  
  <pre><code>{
     E e = ((C)(x)).GetEnumerator();
     try {
        V v;
        while (e.MoveNext()) {
           v = (V)(T)e.Current;
           embedded-statement
        }
     }
     finally {
        … // Dispose e
     }
  }
  </code></pre>
    
    <p>The variable e is not visible to or
    accessible to the expression x or the
    embedded statement or any other source
    code of the program.</p>
  </blockquote>
  
  <p>In case of <code>listArray</code>, the returned enumerator  is saved ( ie its value is saved ) in variable <code>e</code> ( thus variable <code>e</code> is a mutable struct ) .But according to the above excerpt, <code>e</code> is not accesible to my source code, so how would I be able to pass this struct around ( unless I write code that does manually what <code>foreach</code> statement does automatically )?</p>
  
  <p>2) </p>
  
  <blockquote>
    <p>Member lookup is performed on E with the identifier Current and no type arguments. If 
    the member lookup produces no match, the result is an error, or the result is anything 
    except a public instance property that permits reading, an error is produced and no 
    further steps are taken.</p>
  </blockquote>
  
  <p>It seems that if we implement <code>GetEnumerator</code> in the class ( <code>X</code> ) itself, then <code>Current</code> should also be implemented in the class ( <code>E</code> )  itself ( thus <code>E</code> shouldn't explicitly implement <code>Current</code> ), since compiler won't bother to  check for <code>IEnumerator&lt;T&gt; / IEnumerator</code> interfaces in cases where member lookup ( on <code>E</code> with identifier <code>Current</code> ) doesn't produce a match?</p>
  
  <p>3)</p>
  
  <blockquote>
    <p>If there is exactly one type T such that there is an implicit conversion from X to the 
    interface System.Collections.Generic.IEnumerable, then the collection type is this 
    interface, the enumerator type is the interface 
    System.Collections.Generic.IEnumerator, and the element type is T.</p>
  </blockquote>
  
  <p>According to the above, if <code>foreach</code> has to check for <code>IEnumerable&lt;T&gt;</code> interface, then <code>foreach</code> will always use <code>IEnumerator&lt;T&gt;</code> version of <code>Current</code>? Thus, if <code>E</code> explicitly implements <code>IEnumerator&lt;T&gt;</code> version of <code>Current</code> and if it also implements another version of <code>Current</code> in the class itself, the <code>foreach</code> will always call <code>IEnumerable&lt;T&gt;</code> version of <code>Current</code>?  </p>
  
  <p>4) </p>
  
  <blockquote>
    <p>The GetEnumerator method is documented as returning one of these:</p>
    
    <p><a href="http://msdn.microsoft.com/en-us/library/x854yt9s.aspx" rel="noreferrer">http://msdn.microsoft.com/en-us/library/x854yt9s.aspx</a></p>
  </blockquote>
  
  <p>What do you mean by <em>one of these</em> ( as in plural )? Link you provided says <code>GetEnumerator</code> ( as implemented by <code>List&lt;T&gt;</code> ) only returns <code>struct</code> type. </p>
  
  <p>5) </p>
  
  <blockquote>
    <p>g. The collection type is X, the enumerator type is E, and the element type is the type of the Current property</p>
  </blockquote>
  
  <p>Perhaps a useless question - according to above, <code>foreach</code> doesn't check what type of elements some user-defined collection actually stores, but instead assumes that the type of elements is the same as the type returned by <code>Current</code> property? </p>