Может ли компилятор C # использовать утиную типизацию с foreach поверх универсального типа? - PullRequest
4 голосов
/ 06 марта 2019

Было установлено, что компилятор может выполнять уточную типизацию, чтобы устранить некоторые издержки при переборе списка или массива (см. Утиная типизация в компиляторе C # ), поскольку эти типы реализуют свой IEnumerator в виде стека структура

Является ли это случаем, даже если тип является общим, но ограничен для реализации IEnumerable?

Для большей конкретности, может ли опция B работать с меньшими издержками, чем A?

A:

public static IEnumerable<T> Flatten<T>(this IEnumerable<IEnumerable<T>> collection)
{
    foreach (var subCollection in collection)
        foreach (var element in subCollection)
            yield return element;
}

B

public static IEnumerable<T> Flatten<TList, T>(this TList collection)
    where TList : IEnumerable<IEnumerable<T>>
{
    foreach (var subCollection in collection)
        foreach (var element in subCollection)
            yield return element;
}

1 Ответ

6 голосов
/ 06 марта 2019

Нет, в основном.Единственное использование для «B» - это когда TList сам фактически является struct;IL может затем использовать «ограниченный вызов» для вызова оригинального GetEnumerator() без любой части, которая должна содержать оригинальное struct TList значение.

Но: как только вы вызвали GetEnumerator(), вы вернулись в IEnumerator<T> земли, и он будет не использовать пользовательский итератор.

1016 * Все это в основном вопрос спорный в этом случае, потому что итератор блоки также довольно "выделяют".Так что ... если вы избегаете бокса TList, это ваша забота, вы, вероятно, одержимы распределением: в этом случае вы также не напишите блок итератора таким образом.
...