Простое выражение Linq не будет компилироваться
Имея эти основные определения
bool MyFunc(string input)
{
return false;
}
var strings = new[] {"aaa", "123"};
Мне интересно, почему это не скомпилируется:
var b = strings.Select(MyFunc);
Но это будет:
var c = strings.Select(elem => MyFunc(elem));
Сообщение об ошибке: "Аргументы типа для метода" System.Linq.Enumerable.Select(System.Collections.Generic.IEnumerable, System.Func) "не могут быть выведены из использования."
Совет по ошибкам Resharper говорит, что он путается между
Select(this IEnumerable<string>, Func<string, TResult>)
и
Select(this IEnumerable<string>, Func<string, int, TResult>)
... но подпись для MyFunc понятна - для этого требуется один (строковый) параметр.
Может ли кто-нибудь пролить свет здесь?
Ответы
Ответ 1
Вывод типового типа слегка изменился - с точки зрения реализации - между компилятором С# 3 и С# 4. Вот короткая, но полная примерная программа:
using System;
using System.Linq;
class Test
{
static void Main()
{
string[] strings = { "a", "b" };
var results = strings.Select(MyFunc);
}
static bool MyFunc(string input)
{
return true;
}
}
Это компиляция с компилятором С# в .NET 4, но не в .NET 3.5.
Я считаю разумным назвать это исправлением ошибки, поскольку я не думаю, что это было изменение спецификации.
Если вам нужно использовать компилятор из .NET 3.5, вы можете добавить листинг, чтобы уточнить:
var results = strings.Select((Func<string,bool>) MyFunc);
или
var results = strings.Select(new Func<string,bool>(MyFunc));
или вы можете сделать аргумент типа явным:
var results = strings.Select<string, bool>(MyFunc);
Ответ 2
Джон, конечно, прав, как обычно. Дополнительная информация:
Вот статья блога с 2007 года, где я описываю проблему, с которой вы сталкиваетесь:
http://blogs.msdn.com/b/ericlippert/archive/2007/11/05/c-3-0-return-type-inference-does-not-work-on-member-groups.aspx
Основываясь на отзывах по этой статье, мы решили исправить это, но не смогли получить исправление в С# 3 для расписания.
Через несколько месяцев я объявил, что исправление перейдет в С# 4, а не в пакет С# 3:
http://blogs.msdn.com/b/ericlippert/archive/2008/05/28/method-type-inference-changes-part-zero.aspx