C# 使用委托和lambda的奇怪行为

C# 使用委托和lambda的奇怪行为,c#,.net-3.5,lambda,C#,.net 3.5,Lambda,为了在我正在开发的库中引入惰性格式计算,我定义了委托 public delegate string MessageFormatterDelegate(string message, params object[] arguments); public delegate string MessageFormatterCallback(MessageFormatterDelegate formatterDelegate); 和下面这节课的内容 public static class TestCla

为了在我正在开发的库中引入惰性格式计算,我定义了委托

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


编译并正常工作,在控制台中打印
1,2,3
。为什么我必须在第二个lambda表达式中使用
MessageFormatterDelegate
类型限定
message
参数?有什么方法可以改变这种行为吗?

编辑:好的,我现在有一个更简短的示例和解决方法

第一个源文件,
External.cs

public delegate string Callback(System.Action<string> x);
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)
应该是等效的

将向Eric Lippert发送邮件…

更新: 该错误已在C#5中修复。再次为给您带来的不便表示歉意,并感谢您的报告



这似乎与此处描述的已知错误重复:

有关详细信息,请参见我对该问题的回答

这里也有报道:

这只虫子是我的错;我为这个错误道歉。我们将尝试修复C#5

如果你认为你真的发现了一个不同的错误,请让我知道,我们将开始调查


谢谢你的报告,我很感激。

很有趣。看起来像是某种虫子。你有没有用所有不同的C#编译器版本测试过这个问题,看看它是否得到了修复?谢谢。事实上,我已经在Visual Studio 2010 Express Edition下对它进行了测试,新安装了SP1。@DotNetStudent:它在那里工作吗?或者说,这是它失败的地方吗?应该没问题,看看我的答案。对不起,乔恩。我忘了在第一篇文章中添加“外部项目”部分!它在同一个项目中工作,但不来自外部项目。@leppie:推断lambda表达式委托类型。对不起,乔恩。我忘了在第一篇文章中添加“外部项目”部分!它在同一个项目中工作,但不是来自外部项目。@DotNetStudent:那么这个“外部”项目中有多少钱?除了电话?我有一种感觉,我以前可能见过这种情况…@leppie:好的,我已经检查过了-当涉及方法组转换时,它仍然称为类型推断(第7.5.2.13节),但我认为它不适用于匿名函数转换。这似乎是这里描述的已知错误的重复:(有关详细信息,请参阅我对该问题的回答。)Jon,你同意这是重复的吗?如果你认为这是一个不同的bug,那么我会提请David注意,我们会为C#5输入一个bug。谢谢,并为这个错误道歉。@EricLippert:看起来确实是这样。显式调用
Invoke
的解决方法可能是在内部记录额外的信息,如果您还没有得到它的话。我想这可能值得对照C#5编译器进行检查,如果这意味着修复了另一个:)(我回家后可以对照VS11预览进行检查,如果这有用的话,但现在不行。)
Callback callback = action => action.Invoke("hello");