Подтвердить что ты не робот

Странное поведение с использованием делегатов и лямбда

Как средство введения ленивой оценки форматирования в библиотеке, которую я разрабатываю, я определил делегатов

public delegate string MessageFormatterDelegate(string message, params object[] arguments);
public delegate string MessageFormatterCallback(MessageFormatterDelegate formatterDelegate);

и что-то вроде строк следующего класса

public static class TestClass
{
    public static string Evaluate(MessageFormatterCallback formatterCallback)
    {
        return (formatterCallback(String.Format));
    }
}

Однако это ведет себя довольно странно: при запуске из проекта external утверждение

Console.WriteLine(TestClass.Evaluate(message => message("{0},{1},{2}", 1, 2, 3)));

выполняет не компиляцию, сбой при ошибке

Error   1   Delegate 'MessageFormatterDelegate' does not take 4 arguments

а

Console.WriteLine(TestClass.Evaluate((MessageFormatterDelegate message) => message("{0},{1},{2}", 1, 2, 3)));

компилируется и работает без проблем, печатая 1,2,3 в консоли. Почему мне нужно квалифицировать аргумент message с типом MessageFormatterDelegate во втором выражении лямбда? Есть ли способ обойти это поведение?

4b9b3361

Ответ 1

EDIT: Хорошо, теперь у меня есть более короткий пример и обходной путь.

Первый исходный файл, External.cs:

public delegate string Callback(System.Action<string> x);

Второй исходный файл, Test.cs:

class Test
{
    static void Main()
    {
        Callback callback = action => action("hello");
    }
}

Скомпилировать с помощью:

> csc /target:library External.cs
> csc Test.cs /r:External.cs

Ошибка:

Делегирование "Действие" не принимает 1 аргумент

Временное решение: измените тело метода Main на:

Callback callback = action => action.Invoke("hello");

... или включить объявление делегата в той же сборке, которая его использует.

Это определенно похоже на ошибку. Когда компилятор знает, что тип foo является конкретным типом делегирования, тогда foo(arg) и foo.Invoke(arg) должны быть эквивалентными.

Будет ли письмо Эриком Липпертом...

Ответ 2

UPDATE:

Исправлена ​​ошибка в С# 5. Извинитесь за неудобства и благодарность за отчет.


Это, кажется, дубликат известной ошибки, описанной здесь:

'Делегат' System.Action 'не принимает 0 аргументов.' Является ли это ошибкой компилятора С# (lambdas + два проекта)?

Подробнее см. мой ответ на этот вопрос.

Здесь также сообщалось:

С# Ошибка Parser на делегате?

Эта ошибка была моей плохой; Прошу прощения за ошибку. Мы попытаемся получить исправление в С# 5.

Если вы думаете, что на самом деле обнаружили другую ошибку, сообщите мне, и мы начнем расследование.

И спасибо за отчет, я ценю это.