Метод расширения ToList() возвращает a List<TSource>. Следуя той же схеме, ToDictionary() возвращает a Dictionary<TKey, TSource>.
Мне любопытно, почему эти методы не вводят возвращаемые значения как IList<TSource> и IDictionary<TKey, TSource> соответственно. Это кажется еще более странным, потому что ToLookup<TSource, TKey> выводит возвращаемое значение как интерфейс вместо фактической реализации.
Рассматривая источник этих методов расширения с помощью dotPeek или другого декомпилятора, мы видим следующую реализацию (показывая ToList(), потому что она короче):
public static List<TSource> ToList<TSource>(this IEnumerable<TSource> source) {
if (source == null) throw Error.ArgumentNull("source");
return new List<TSource>(source);
}
Итак, почему этот метод определяет его возвращаемое значение как конкретную реализацию интерфейса, а не самого интерфейса? Единственным изменением будет тип возврата.
Мне любопытно, потому что расширения IEnumerable<> очень согласованы в своих подписях, за исключением этих двух случаев. Я всегда думал, что это немного странно.
Кроме того, чтобы сделать вещи еще более запутанными, документация для ToLookup() гласит:
Создает поиск из IEnumerable в соответствии с указанная функция выбора ключа.
но возвращаемый тип ILookup<TKey, TElement>.
В Edulinq Джон Скит упоминает, что тип возврата List<T> вместо IList<T>, но не касается темы далее.
Обширный поиск не дал ответа, поэтому я прошу вас:
Есть ли какое-либо конструкторское решение, не набирающее возвращаемые значения в качестве интерфейсов, или это просто случайность?