What concrete type does 'yield return' return?

后端 未结 3 1047
谎友^
谎友^ 2020-12-19 00:56

What is the concrete type for this IEnumerable?

private IEnumerable GetIEnumerable()
{
    yield return \"a\";
    y         


        
相关标签:
3条回答
  • 2020-12-19 01:30

    The compiler will automatically generate a class that implements both IEnumerable<T> and IEnumerator<T> (in the same class).

    Jon Skeet has a detailed explanation.

    0 讨论(0)
  • 2020-12-19 01:38

    The concrete implementation of IEnumerable<string> returned by the method is an anonymous type generated by the compiler

    Console.WriteLine(GetIEnumerable().GetType());
    

    Prints :

    YourClass+<GetIEnumerable>d__0
    
    0 讨论(0)
  • 2020-12-19 01:47

    It's a compiler-generated type. The compiler generates an IEnumerator<string> implementation that returns three "a" values and an IEnumerable<string> skeleton class that provides one of these in its GetEnumerator method.

    The generated code looks something like this*:

    // No idea what the naming convention for the generated class is --
    // this is really just a shot in the dark.
    class GetIEnumerable_Enumerator : IEnumerator<string>
    {
        int _state;
        string _current;
    
        public bool MoveNext()
        {
            switch (_state++)
            {
                case 0:
                    _current = "a";
                    break;
                case 1:
                    _current = "a";
                    break;
                case 2:
                    _current = "a";
                    break;
                default:
                    return false;
            }
    
            return true;
        }
    
        public string Current
        {
            get { return _current; }
        }
    
        object IEnumerator.Current
        {
            get { return Current; }
        }
    
        void IEnumerator.Reset()
        {
            // not sure about this one -- never really tried it...
            // I'll just guess
            _state = 0;
            _current = null;
        }
    }
    
    class GetIEnumerable_Enumerable : IEnumerable<string>
    {
        public IEnumerator<string> GetEnumerator()
        {
            return new GetIEnumerable_Enumerator();
        }
    
        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    }
    

    Or maybe, as SLaks says in his answer, the two implementations end up in the same class. I wrote this based on my choppy memory of generated code I'd looked at before; really, one class would suffice, as there's no reason the above functionality requires two.

    In fact, come to think of it, the two implementations really should fall within a single class, as I just remembered the functions that use yield statements must have a return type of either IEnumerable<T> or IEnumerator<T>.

    Anyway, I'll let you perform the code corrections to what I posted mentally.

    *This is purely for illustration purposes; I make no claim as to its real accuracy. It's only to demonstrate in a general way how the compiler does what it does, based on the evidence I've seen in my own investigations.

    0 讨论(0)
提交回复
热议问题