【问题标题】:Strange Behaviour Using Delegates and Lambdas使用委托和 Lambda 的奇怪行为
【发布时间】:2012-02-03 11:46:40
【问题描述】:

作为在我正在开发的库中引入惰性格式评估的一种方法,我定义了委托

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。为什么我必须在第二个 lambda 表达式中使用 MessageFormatterDelegate 类型限定 message 参数?有没有办法规避这种行为?

【问题讨论】:

  • 有趣。看起来像某种错误。您是否使用所有不同的 C# 编译器版本对此进行了测试以查看它是否已修复?
  • 谢谢leppie。事实上,我已经在新安装了 SP1 的 Visual Studio 2010 Express Edition 下对其进行了测试。
  • @DotNetStudent:它在那里工作吗,或者它对你来说是失败的地方?应该没问题 - 看看我的回答。
  • 对不起乔恩。我忘了在第一篇文章中添加“外部项目”部分!在同一个项目中它可以工作,但不是来自外部项目。
  • @leppie:推断 lambda 表达式委托类型。 ((c)乔恩·斯基特:-P)

标签: c# .net-3.5 lambda


【解决方案1】:

更新:

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


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

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

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

这里也有报道:

C# Parser Bug on delegate?

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

如果您认为您确实发现了一个不同错误,请告诉我,我们将开始调查。

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

【讨论】:

    【解决方案2】:

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

    第一个源文件,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
    

    错误:

    委托 'Action' 不接受 1 个参数

    解决方法:将Main 方法的主体更改为:

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

    ...或在使用它的同一程序集中包含委托声明。

    这对我来说绝对是一个错误。当编译器知道foo的类型是特定的委托类型时,那么foo(arg)foo.Invoke(arg)应该是等价的。

    将邮寄 Eric Lippert...

    【讨论】:

    • 对不起乔恩。我忘了在第一篇文章中添加“外部项目”部分!在同一个项目中它可以工作,但不是来自外部项目。
    • @DotNetStudent:那么这个“外部”项目有多少?除了电话以外的一切?我有一种感觉,我可能以前见过这个......
    • @leppie:好的,我已经检查过了——当涉及到方法组转换时,它仍然被称为类型推断(第 7.5.2.13 节),但我认为它不是用于匿名函数转换。
    • 这似乎与此处描述的已知错误重复:stackoverflow.com/questions/4466859/…(有关详细信息,请参阅我对该问题的回答。)乔恩,您同意这是重复的吗?如果您认为这是一个不同的错误,那么我会提请大卫注意,我们会为 C# 5 输入一个错误。谢谢,并为错误道歉。
    • @EricLippert:当然看起来像。显式调用Invoke 的解决方法可能是内部记录的额外信息,如果您还没有的话。我想这可能值得检查 C# 5 编译器,如果那是为了修复另一个:)(我可以在回家时检查 VS 11 Preview 是否有用,但不是现在。)跨度>
    猜你喜欢
    • 1970-01-01
    • 2013-09-14
    • 1970-01-01
    • 1970-01-01
    • 2018-06-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-23
    相关资源
    最近更新 更多