Странное поведение с использованием делегатов и лямбд - PullRequest
15 голосов
/ 03 февраля 2012

В качестве средства представления оценки ленивого форматирования в разрабатываемой мной библиотеке я определил делегатов

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));
    }
}

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

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 во втором лямбда-выражении?Есть ли способ обойти это поведение?

Ответы [ 2 ]

11 голосов
/ 03 февраля 2012

UPDATE:

Ошибка была исправлена ​​в C # 5. Снова извиняюсь за неудобства, и спасибо за отчет.


Похоже, что это дубликат известной ошибки, описанной здесь:

'Делегат' System.Action 'не принимает 0 аргументов.' Это ошибка компилятора C # (лямбда + два проекта)?

Смотрите подробности в моем ответе на этот вопрос.

Также сообщалось здесь:

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

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

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

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

7 голосов
/ 03 февраля 2012

РЕДАКТИРОВАТЬ: Хорошо, теперь у меня есть гораздо более короткий пример и обходной путь.

Первый исходный файл, 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) должны быть эквивалентны.

Будет отправлять по почте Эрику Липперту ...

...