比较 Actions/Funcs 时结果不一致

Inconsistent result when comparing Actions/Funcs

我一直在尝试缓存某些ActionsFuncs的结果。 为此,我将 Actions/Funcs 及其各自的结果存储在 Dictionary 中。

在执行此操作时,我偶然发现了一些意想不到的事情(示例已简化):

        var lstActions = new List<Action>();

        for (int i = 0; i < 2; i++)
        {
            lstActions.Add(() => { });
        }

        bool bEqual = lstActions[0] == lstActions[1]; // Result = true

--

        var lstActions = new List<Action>();

        lstActions.Add(() => { });
        lstActions.Add(() => { });

        bool bEqual = lstActions[0] == lstActions[1]; // Result = false

谁能解释为什么结果不同?

编译器尽量减少它创建的 delegate 对象的数量。为此,它通常会在可能的情况下缓存实例。

由于您的第一个示例定义了单个 lambda 并且它不捕获任何循环变量,因此单个委托实例就足够了。

在第二个示例中,您定义了两个不同的匿名方法,编译器不会检查它们的代码是否相同,因为这种情况很少见,并且会创建两个委托实例。

然而,这是编译器的一个实现细节,我不会以任何方式依赖它。

您将看到有关编译器如何将 lambda 表达式转换为指向编译器生成的方法的委托的实现细节。

由于编译器的变化、调试与发布版本的变化,或者任何 lambda 表达式内容的变化,此行为可能会发生变化。

解释你目前的行为:

出现在源代码中的每个 lambda 都被编译成一个单独的方法。因此,您的第二个示例生成了两个方法(恰好具有相同的主体),并且委托不相同。

您的第一个示例在源代码中只有一个 lambda ,因此它编译为一个方法。因为 lambda 不使用任何局部变量,它不会生成闭包 class,所以委托的 MethodTarget 属性是相同的。