Какой конкретный тип 'урожай возвращает' возврат?

Каков конкретный тип для этого IEnumerable<string>?

private IEnumerable<string> GetIEnumerable()
{
    yield return "a";
    yield return "a";
    yield return "a";
}
9
задан Timwi 11 August 2010 в 00:14
поделиться

3 ответа

Это тип, созданный компилятором . Компилятор создает реализацию IEnumerator , которая возвращает три значения «a» и скелетный класс IEnumerable , который предоставляет одно из них в своем GetEnumerator метод.

Сгенерированный код выглядит что-то так *:

// 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();
    }
}

Или, может быть, как говорит SLaks в своем ответе, две реализации попадают в один и тот же класс. Я написал это на основе моей изменчивой памяти сгенерированного кода, на который я смотрел раньше; действительно, одного класса будет достаточно, поскольку нет причин, по которым вышеуказанная функциональность требует двух.

На самом деле, если подумать, две реализации действительно должны попадать в один класс, так как я только что вспомнил, что функции, которые используют операторы yield , должны иметь возвращаемый тип из либо IEnumerable , либо IEnumerator .

В любом случае, я позволю вам внести исправления в код того, что я мысленно отправил.

* Это чисто для иллюстративных целей; Я не претендую на его истинную точность. Это только для того, чтобы в общих чертах продемонстрировать, как компилятор делает то, что он делает, на основе свидетельств, которые я видел в своих собственных исследованиях.

8
ответ дан 4 December 2019 в 12:15
поделиться

Конкретная реализация IEnumerable , возвращаемая методом, является анонимным типом, сгенерированным компилятором

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

Выводит:

YourClass+<GetIEnumerable>d__0
2
ответ дан 4 December 2019 в 12:15
поделиться

Компилятор автоматически сгенерирует класс, который реализует как IEnumerable , так и IEnumerator (в том же классе) .

У Джона Скита есть подробное объяснение .

7
ответ дан 4 December 2019 в 12:15
поделиться
Другие вопросы по тегам:

Похожие вопросы: