У меня есть два статических метода расширения, которые похожи в том, что один принимает IEnumerable, а другой просто T. Каждый из них возвращает ExpandoObject, и у меня есть два для целей оптимизации, так как я использую Reflection внутри каждого.
Здесьмои сигнатуры методов:
public static ExpandoObject DoSomething<TSource>(this TSource source, string somethingElse)
public static ExpandoObject DoSomething<TSource>(this IEnumerable<TSource> source, string somethingElse)
Сначала я написал последний, а затем выписал тестовый модуль, чтобы проверить его, он прошел. Затем я написал прежнее расширение, и теперь мой модульный тест с IEnumerable терпит неудачу, потому что он соответствует TSource (как список), а не соответствует сигнатуре IEnumerable.
Я бы ожидал, что он выберет наиболееузкое расширение для сопоставления, но, хотя оно показывается как совпадение с любой подписью в Intellisense, оно всегда выбирает реализацию без IEnumerable (и я не могу определить способ переопределить этот выбор).
1) IsЕсть ли способ заставить его выбрать более узкое соответствие или иным образом выбрать, какое расширение я хочу использовать? 2) В качестве альтернативы, есть ли способ защитить типы, переданные для защиты реализации TSource, от получения любых типов IEnumerable?
Редактировать : Продолжая играть с этим, я все еще в замешательствеотносительно того, как компилятор выбирает соответствующее расширение для использования.
Если я сообщаю тип вывода вместо использования var, как показано ниже, он все равно выбирает объектный подход и возвращает только один ExpandoObject вместо IEnumerable из них:
IEnumerable<MyObj> data = new List<MyObj>();
var results = results.DoSomething("");
Это правильно отобразит расширение, которое возвращает IEnumerable, но если я сделаю следующее:
var data = new List<MyObj>();
var results = results.DoSomething("");
Компилятор выберетВместо этого объектно-ориентированный подход возвратит один ExpandoObject.
Учитывая, что List реализует IEnumerable, почему компилятор выбирает сопоставление с объектом для определения соответствующего расширения вместо выбора версии IEnumerable, если я не приведу явное приведениепеременная для ввода как IEnumerable?
Итак, вопрос № 3: что информирует компилятор о том, какой из них использовать? Он явно выберет самый узкий из доступных вариантов, если это явное совпадение типов, но почему он сразу же прибегает к самому широкому методу, даже если доступно более узкое совпадение (например, ввод списка)?