Простое выражение 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