Strange Behaviour Using Delegates and Lambdas

2019-03-18 01:20发布

As a means of introducing lazy formatting evaluation in a library I am developing, I have defined the delegates

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

and something along the lines of the following class

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

However, this is behaving strangely enough: when running from an external project, the statement

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

does not compile, failing with the error

Error   1   Delegate 'MessageFormatterDelegate' does not take 4 arguments

while

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

compiles and works with no problems, printing 1,2,3 in the console. Why do I have to qualify the message argument with MessageFormatterDelegate type in the second lambda expression? Is there any way to circunvent this behaviour?

2条回答
疯言疯语
2楼-- · 2019-03-18 01:54

EDIT: Okay, I've now got a much shorter example and a workaround.

First source file, External.cs:

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

Second source file, Test.cs:

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

Compile with:

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

Error:

Delegate 'Action' does not take 1 arguments

Workaround: change the body of the Main method to:

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

... or include the delegate declaration in the same assembly which uses it.

This definitely looks like a bug to me. When the compiler knows that the type of foo is a particular delegate type, then foo(arg) and foo.Invoke(arg) should be equivalent.

Will mail Eric Lippert...

查看更多
趁早两清
3楼-- · 2019-03-18 02:06

UPDATE:

The bug has been fixed in C# 5. Apologies again for the inconvenience, and thanks for the report.


This appears to be a duplicate of the known bug described here:

'Delegate 'System.Action' does not take 0 arguments.' Is this a C# compiler bug (lambdas + two projects)?

See my answer to that question for details.

It was also reported here:

C# Parser Bug on delegate?

This bug was my bad; I apologize for the error. We'll try to get a fix in C# 5.

If you think that you have actually found a different bug, please let me know and we'll start an investigation.

And thanks for the report, I appreciate it.

查看更多
登录 后发表回答