比较 Actions/Funcs 时结果不一致
Inconsistent result when comparing Actions/Funcs
我一直在尝试缓存某些Actions
和Funcs
的结果。
为此,我将 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,所以委托的 Method
和 Target
属性是相同的。
我一直在尝试缓存某些Actions
和Funcs
的结果。
为此,我将 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,所以委托的 Method
和 Target
属性是相同的。