C# 比较操作/函数时结果不一致

C# 比较操作/函数时结果不一致,c#,comparison,func,C#,Comparison,Func,我一直在尝试缓存某些操作和函数的结果。 为此,我将操作/函数存储在字典中,并附带相应的结果 在这样做时,我偶然发现了一些意想不到的事情(示例简化): var lstActions=new List(); 对于(int i=0;i{}); } bool bEqual=lstActions[0]==lstActions[1];//结果=真 -- var lstActions=new List(); lstActions.Add(()=>{}); lstActions.Add(()=>{}); bo

我一直在尝试缓存某些
操作
函数
的结果。 为此,我将
操作
/
函数
存储在
字典
中,并附带相应的结果

在这样做时,我偶然发现了一些意想不到的事情(示例简化):

var lstActions=new List();
对于(int i=0;i<2;i++)
{
lstActions.Add(()=>{});
}
bool bEqual=lstActions[0]==lstActions[1];//结果=真
--

var lstActions=new List();
lstActions.Add(()=>{});
lstActions.Add(()=>{});
bool bEqual=lstActions[0]==lstActions[1];//结果=错误

有人能解释为什么结果不同吗?

编译器试图最小化它创建的
委托
对象的数量。为此,它通常在可能的情况下缓存实例

因为您的第一个示例定义了一个lambda,并且它不捕获任何循环变量,所以一个委托实例就足够了

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


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

编译器尝试最小化它创建的
委托
对象的数量。为此,它通常在可能的情况下缓存实例

因为您的第一个示例定义了一个lambda,并且它不捕获任何循环变量,所以一个委托实例就足够了

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


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

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

此行为可能会因编译器、调试版本与发布版本的更改或任何lambda内容的更改而更改

要解释您当前的行为:

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


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

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

此行为可能会因编译器、调试版本与发布版本的更改或任何lambda内容的更改而更改

要解释您当前的行为:

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


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

为什么它们不应该不同呢?对我来说,在for循环中添加两个动作的代码与分别添加两个动作的代码是相同的。所以除非我遗漏了什么,否则它们应该完全相同。为什么它们不应该不同呢?对我来说,在for循环中添加这两个动作的代码与分别添加这两个动作的代码是一样的。所以除非我遗漏了什么,否则它们应该是完全一样的。我怀疑是这样的。谢谢你的澄清,我会把这个标记为答案。我怀疑是这样的。谢谢你的澄清,我将把这个标记为答案。也谢谢你的回答。你的答案和@SLaks都回答了这个问题。@Jens是的,我们可能是同时写的,并且隔了几秒钟贴出来:)也感谢你的回答。你的答案和@SLaks都回答了这个问题。@Jens是的,我们可能是同时写的,并且隔几秒钟发布:)
        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