lambdas是委托类型的构造函数吗?

lan*_*nce 9 c# lambda constructor rhino-mocks

我发现当我使用lambdas作为被断言方法的参数时,Rhino Mocks的AssertWasCalled失败了.

测试:
_mockDoer.AssertWasCalled(x => x.Print(y => Console.WriteLine("hi")));

测试中的内部代码系统:
_doer.Print(y => Console.WriteLine("hi")));

这让我认为lambdas实际上是委托类型的构造函数.

当我将lambdas视为委托类型的构造函数时,我是否遗漏了任何重要内容?

Jon*_*eet 9

好吧,他们在"构造函数"这个词的任何正常用法中都不是真正的"构造函数".

它们是可以转换为委托类型或表达式树类型的表达式 - 后者在进程外LINQ时是必不可少的.

如果您真的在问是否期望使用两个"等效"lambda表达式可以创建不相等的委托实例:是的,它是.IIRC,C#语言规范甚至提到了这种情况.

但是,多次使用相同的lambda表达式并不总是会创建不同的实例:

using System;

class Test
{
    static void Main(string[] args)
    {
        Action[] actions = new Action[2];
        for (int i = 0; i < 2; i++)
        {
            actions[i] = () => Console.WriteLine("Hello");
        }
        Console.WriteLine(actions[0] == actions[1]);
    }
}
Run Code Online (Sandbox Code Playgroud)

在我的盒子上,它实际打印True- actions[0]并且actions[1]具有完全相同的值 - 它们引用相同的实例.的确,我们可以走得更远:

using System;

class Test
{
    static void Main(string[] args)
    {
        object x = CreateAction();
        object y = CreateAction();
        Console.WriteLine(x == y);
    }

    static Action CreateAction()
    {
        return () => Console.WriteLine("Hello");
    }
}
Run Code Online (Sandbox Code Playgroud)

再次,这打印True.它不能保证,但是这里编译器实际上已经创建了一个静态字段来在第一次需要时缓存委托 - 因为它不捕获任何变量等.

基本上,这是一个编译器实现的细节,你应该依靠.

  • +1.我不知道这个>>"两个"等价的"lambda表达式可以创建不相等的委托实例:是的,它是`. (2认同)

Eri*_*ert 6

只是为了扩展Jon的(优秀,一如既往)答案:在当前的C#实现中,如果"相同"的lambda出现在两个不同的源代码位置,那么这两个lambdas永远不会实现为相等的委托.但是,我们保留在未来检测这种情况并统一它们的权利.

反向是否成立也与实现有关.如果从特定源代码位置的lambda创建了两个委托,则委托可能会也可能不具有相等性.在某些情况下,委托不可能具有相等性(例如,因为它们在局部变量的不同实例上被关闭).在情况下它可以让他们拥有平等的,大多数时候他们做什么的时候,但也有少数情况下,我们可以执行该优化和不这样做,只是因为编译器还没有成熟的不够.