У меня перегружены универсальные методы, которые выглядят так:
public static T DoSomething<T>(T val)
{
return val;
}
public static IEnumerable<T> DoSomething<T>(IEnumerable<T> vals)
{
return vals.Select(x => DoSomething(x));
}
Проблема, с которой я сталкиваюсь, заключается в том, что следующий код не будет компилироваться:
var myList = new List<SomeObject>();
// This will not compile
PropertyOfTypeIEnumerable_SomeObject = MyStaticClass.DoSomething(myList);
Компилятор жалуется, что не может конвертировать SomeObject
в IEnumerable<SomeObject>
. Это указывает на то, что компилятор выбирает первую версию DoSomething, которая принимает универсальный тип T, в отличие от второй версии, которая принимает более ограничительный универсальный тип IEnumerable.
Я могу подтвердить это, переименовав второй перегруженный метод в DoSomethingList и явно вызвав это имя:
public static T DoSomething<T>(T val)
{
return val;
}
public static IEnumerable<T> DoSomethingList<T>(IEnumerable<T> vals)
{
return vals.Select(x => DoSomething(x));
}
// ...
var myList = new List<SomeObject>();
// This compiles ok
PropertyOfTypeIEnumerable_SomeObject = MyStaticClass.DoSomethingList(myList);
Мой вопрос заключается в том, почему компилятор не выбирает наиболее ограничивающую подходящую универсальную реализацию для вызова, и есть ли способ, которым я могу получить такое поведение, не называя его однозначно и не вызывая его явно? Если бы в примере вызывались перегрузки для разных объектов, которые унаследованы друг от друга, тогда он выбрал бы наиболее ограничительную перегрузку на основе объявленного типа переменной. Почему он не делает это и для дженериков?
Другим вариантом было бы не перегружать методы, а проверять внутри метода DoSomething, чтобы увидеть, можно ли присвоить T из IEnumerable <>, но тогда я не знаю, как на самом деле привести его к чему-то, что я мог бы вызвать Включен метод Linq, и я не знаю, как заставить компилятор быть в порядке с возвратом результата этого метода Linq, поскольку I будет знать, что возвращаемый результат должен быть IEnumerable, но компилятор не будет.