ЗАКЛЮЧИТЕЛЬНОЕ ОБНОВЛЕНИЕ:
Ошибка была исправлена в C # 5. Снова извиняюсь за неудобства, и спасибо за отчет.
Исходный анализ:
Я могу воспроизвести проблему с помощью компилятора командной строки.Это конечно похоже на ошибку.Это, наверное, моя вина;Извини за это.(Я написал весь код проверки преобразования лямбда-в-делегате.)
Я сейчас в кофейне и отсюда у меня нет доступа к источникам компилятора.Я постараюсь найти время, чтобы воспроизвести это в отладочной сборке завтра и посмотреть, смогу ли я решить, что происходит.Если я не найду время, я буду вне офиса до Рождества.
Ваше наблюдение, что введение переменной типа Action приводит к исчезновению проблемы, чрезвычайно интересно.Компилятор поддерживает множество кэшей как по соображениям производительности, так и для анализа, требуемого спецификацией языка.В частности, у лямбд и локальных переменных много сложной логики кэширования.Я был бы готов поспорить на доллар, что какой-то кеш здесь инициализируется или вводится неправильно, и что использование локальной переменной заполняет правильное значение в кеше.
Спасибо задоклад!
ОБНОВЛЕНИЕ: Я сейчас в автобусе, и он только что пришел ко мне;Я думаю, что я точно знаю, что не так.Компилятор ленивый , особенно когда речь идет о типах, полученных из метаданных.Причина в том, что в ссылочных сборках могут быть сотни тысяч типов, и нет необходимости загружать информацию обо всех из них.Вероятно, вы собираетесь использовать их менее чем на 1%, поэтому давайте не будем тратить много времени и средств на загрузку памяти, которые вы никогда не собираетесь использовать.На самом деле лень идет глубже, чем это;тип проходит через несколько «стадий», прежде чем его можно будет использовать.Сначала известно его имя, затем его базовый тип, затем является ли его иерархия базового типа обоснованной (ациклический и т. Д.), Затем его ограничения параметров типа, затем его члены, а затем, являются ли члены обоснованными (что переопределяет что-то, переопределяетс той же сигнатурой и т. д.) Держу пари, что логике преобразования не удается вызвать метод, который говорит «убедитесь, что типы всех параметров делегата имеют их известные члены», прежде чемпроверяет подпись делегата вызова на совместимость.Но код, который делает локальную переменную, вероятно, делает .Я думаю, что во время проверки преобразования тип Action может даже не иметь метода invoke, поскольку это касается компилятора.
Мы скоро выясним.
ОБНОВЛЕНИЕ: Мои психические способностисильны этим утром.Когда разрешение перегрузки пытается определить, существует ли метод Invoke типа делегата, который принимает нулевые аргументы, он находит нулевых методов Invoke на выбор .Мы должны убедиться, что метаданные типа делегата полностью загружены, прежде чем мы сделаем разрешение перегрузки.Как странно, что это осталось незамеченным так долго;это репродукция в C # 3.0.Конечно, он не воспроизводится в C # 2.0 просто потому, что не было лямбд;анонимные методы в C # 2.0 требуют явного указания типа, который создает локальный, который, как мы знаем, загружает метаданные.Но я бы предположил, что основная причина ошибки - то, что разрешение перегрузки не заставляет загружать метаданные для вызова - восходит к C # 1.0.
В любом случае, захватывающая ошибка, спасибо за отчет.Очевидно, у вас есть обходной путь.Я прослежу, чтобы QA отследил его отсюда, и мы постараемся исправить его для C # 5. (Мы пропустили окно для Service Pack 1, который уже находится в бета-версии .)