Does Class need to implement IEnumerable to use Foreach

前端 未结 11 1753
慢半拍i
慢半拍i 2020-12-09 11:04

This is in C#, I have a class that I am using from some else\'s DLL. It does not implement IEnumerable but has 2 methods that pass back a IEnumerator. Is there a way I can u

11条回答
  •  [愿得一人]
    2020-12-09 11:18

    The type only requires to have a public/non-static/non-generic/parameterless method named GetEnumerator which should return something that has a public MoveNext method and a public Current property. As I recollect Mr Eric Lippert somewhere, this was designed so as to accommodate pre generic era for both type safety and boxing related performance issues in case of value types.

    For instance this works:

    class Test
    {
        public SomethingEnumerator GetEnumerator()
        {
    
        }
    }
    
    class SomethingEnumerator
    {
        public Something Current //could return anything
        {
            get { }
        }
    
        public bool MoveNext()
        {
    
        }
    }
    
    //now you can call
    foreach (Something thing in new Test()) //type safe
    {
    
    }
    

    This is then translated by the compiler to:

    var enumerator = new Test().GetEnumerator();
    try {
       Something element; //pre C# 5
       while (enumerator.MoveNext()) {
          Something element; //post C# 5
          element = (Something)enumerator.Current; //the cast!
          statement;
       }
    }
    finally {
       IDisposable disposable = enumerator as System.IDisposable;
       if (disposable != null) disposable.Dispose();
    }
    

    From 8.8.4 section of the spec.


    Something worth noting is the enumerator precedence involved - it goes like if you have a public GetEnumerator method, then that is the default choice of foreach irrespective of who is implementing it. For example:

    class Test : IEnumerable
    {
        public SomethingEnumerator GetEnumerator()
        {
            //this one is called
        }
    
        IEnumerator IEnumerable.GetEnumerator()
        {
    
        }
    }
    

    (If you don't have a public implementation (ie only explicit implementation), then precedence goes like IEnumerator > IEnumerator.)

提交回复
热议问题