public class C
{
public void M()
{
string hello = "Hello, world!";
SynchronizationContext.Current.Post(_ => Console.WriteLine(hello), null);
}
}
结果是这样的
public class C
{
[CompilerGenerated]
private sealed class <>c__DisplayClass0_0
{
public string hello;
[NullableContext(2)]
internal void <M>b__0(object _)
{
Console.WriteLine(hello);
}
}
public void M()
{
<>c__DisplayClass0_0 <>c__DisplayClass0_ = new <>c__DisplayClass0_0();
<>c__DisplayClass0_.hello = "Hello, world!";
SynchronizationContext.Current.Post(new SendOrPostCallback(<>c__DisplayClass0_.<M>b__0), null);
}
}
原来是同一个班级。
但没有捕获的参数
public class C
{
public void M()
{
string hello = "Hello, world!";
SynchronizationContext.Current.Post(h => Console.WriteLine(h), hello);
}
}
public class C
{
[Serializable]
[CompilerGenerated]
private sealed class <>c
{
public static readonly <>c <>9 = new <>c();
public static SendOrPostCallback <>9__0_0;
[NullableContext(2)]
internal void <M>b__0_0(object h)
{
Console.WriteLine(h);
}
}
public void M()
{
string state = "Hello, world!";
SynchronizationContext.Current.Post(<>c.<>9__0_0 ?? (<>c.<>9__0_0 = new SendOrPostCallback(<>c.<>9.<M>b__0_0)), state);
}
}
public class C
{
public void M()
{
string hello = "Hello, world!";
SynchronizationContext.Current.Post(Console.WriteLine, hello);
}
}
鼓声滚...
public class C
{
[CompilerGenerated]
private static class <>O
{
public static SendOrPostCallback <0>__WriteLine;
}
public void M()
{
string state = "Hello, world!";
SynchronizationContext.Current.Post(<>O.<0>__WriteLine ?? (<>O.<0>__WriteLine = new SendOrPostCallback(Console.WriteLine)), state);
}
}
Lambda 也可以是静态的,例如:
Lambda 被编译成一个方法,在一个单独的类中,这不完全是一个闭包。但为了实现最佳的亮度和性能,应避免在 lambda 中捕获参数。
我们来比较一下 IL 反编译会显示什么。
这是一个捕获的参数
结果是这样的
原来是同一个班级。
但没有捕获的参数
发生了什么?没错,lambda 变成了静态,即使我没有明确地写入它是静态的
static
。编译器很聪明,他自己猜到了。更准确地说,这并不完全是静态的,而是单例。但无论如何,这已经意味着不会有额外的分配。因此,请注意执行这种优化的可能性,即通过实参传递数据,而不是通过捕获的实参传递数据。
性能上的差异在于,当 lambda 不是静态时,需要花费一点时间来创建它所在的类的实例并向其传递参数。
顺便说一下,如果按照 IDE 的建议完全删除 lambda,将会发生以下情况:
鼓声滚...
单例已经消失,现在我们只有一个静态委托。
另外,任何 lambda 本身都意味着将调用包装在委托中,所以是的,如果可以在常规方法中编写代码 - 直接编写和调用,那么您可以完全不需要委托。
至于静态方法和当前实例方法的性能差异,后者快一点。无论如何,这就是我曾经运行的基准测试所显示的结果,解决了对性能要求非常高的任务。
顺便说一句,上面显示的反编译 C# 代码几乎无法洞察性能。要获得这样的想法,您需要比较 JIT 编译器生成的汇编程序并运行基准测试。基准测试将显示什么更快,汇编器将显示为什么它更快。
不正确。如果 lambda 不使用闭包,那么它将变成静态方法。如果确实如此,那么为什么不将其替换为静态方法呢?