RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1599618
Accepted
D .Stark
D .Stark
Asked:2024-11-13 02:24:49 +0000 UTC2024-11-13 02:24:49 +0000 UTC 2024-11-13 02:24:49 +0000 UTC

C# Lambda 表达式性能

  • 772

从性能角度来看,使用静态方法是否比 lambda 表达式更好?由于lambda表达式每次都会生成一个闭包对象并保存对所使用的局部变量的引用。

c#
  • 2 2 个回答
  • 58 Views

2 个回答

  • Voted
  1. Best Answer
    aepot
    2024-11-13T03:32:49Z2024-11-13T03:32:49Z

    Lambda 也可以是静态的,例如:

    SynchronizationContext.Current.Post(static _ => Console.WriteLine(), null);
    

    Lambda 被编译成一个方法,在一个单独的类中,这不完全是一个闭包。但为了实现最佳的亮度和性能,应避免在 lambda 中捕获参数。

    我们来比较一下 IL 反编译会显示什么。

    这是一个捕获的参数

    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);
        }
    }
    

    发生了什么?没错,lambda 变成了静态,即使我没有明确地写入它是静态的static。编译器很聪明,他自己猜到了。更准确地说,这并不完全是静态的,而是单例。但无论如何,这已经意味着不会有额外的分配。

    因此,请注意执行这种优化的可能性,即通过实参传递数据,而不是通过捕获的实参传递数据。

    性能上的差异在于,当 lambda 不是静态时,需要花费一点时间来创建它所在的类的实例并向其传递参数。

    顺便说一下,如果按照 IDE 的建议完全删除 lambda,将会发生以下情况:

    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 本身都意味着将调用包装在委托中,所以是的,如果可以在常规方法中编写代码 - 直接编写和调用,那么您可以完全不需要委托。

    至于静态方法和当前实例方法的性能差异,后者快一点。无论如何,这就是我曾经运行的基准测试所显示的结果,解决了对性能要求非常高的任务。

    顺便说一句,上面显示的反编译 C# 代码几乎无法洞察性能。要获得这样的想法,您需要比较 JIT 编译器生成的汇编程序并运行基准测试。基准测试将显示什么更快,汇编器将显示为什么它更快。

    • 5
  2. Qwertiy
    2024-11-13T03:32:00Z2024-11-13T03:32:00Z

    不正确。如果 lambda 不使用闭包,那么它将变成静态方法。如果确实如此,那么为什么不将其替换为静态方法呢?

    • 4

相关问题

  • 使用嵌套类导出 xml 文件

  • 分层数据模板 [WPF]

  • 如何在 WPF 中为 ListView 手动创建列?

  • 在 2D 空间中,Collider 2D 挂在玩家身上,它对敌人的重量相同,我需要它这样当它们碰撞时,它们不会飞向不同的方向。统一

  • 如何在 c# 中使用 python 神经网络来创建语音合成?

  • 如何知道类中的方法是否属于接口?

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    我看不懂措辞

    • 1 个回答
  • Marko Smith

    请求的模块“del”不提供名为“default”的导出

    • 3 个回答
  • Marko Smith

    "!+tab" 在 HTML 的 vs 代码中不起作用

    • 5 个回答
  • Marko Smith

    我正在尝试解决“猜词”的问题。Python

    • 2 个回答
  • Marko Smith

    可以使用哪些命令将当前指针移动到指定的提交而不更改工作目录中的文件?

    • 1 个回答
  • Marko Smith

    Python解析野莓

    • 1 个回答
  • Marko Smith

    问题:“警告:检查最新版本的 pip 时出错。”

    • 2 个回答
  • Marko Smith

    帮助编写一个用值填充变量的循环。解决这个问题

    • 2 个回答
  • Marko Smith

    尽管依赖数组为空,但在渲染上调用了 2 次 useEffect

    • 2 个回答
  • Marko Smith

    数据不通过 Telegram.WebApp.sendData 发送

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5