如何在C#9 中使用static匿名函数

匿名函数 在 C# 中已经出现很多年了,虽然匿名函数用起来很爽,但代价是不小的,为了避免不必要那些你意想不到的内存分配,这就是为什么 C#9 中引入 static 匿名函数的原因,这篇文章我们将会讨论如何使用 静态匿名函数 以及为什么要用。

匿名方法的代价

匿名方法代价不低,因为它有 委托调用 方面的开销,什么意思呢?如果你的 lambda 里需要捕获封闭方法的局部变量或者参数,那么就会存在两种堆分配,一种是委托上的分配,另一种是闭包上的分配,如果你的 lambda 仅仅捕获一个封闭方法的实例状态,那么仅会有委托分配,如果你的 lambda 什么都不捕获或者仅捕获一个静态状态,那么就没有任何分配。

如果你有点懵的话,使用下面的例子加深理解。

int y = 1;
MyMethod(x => x + y);

上面代码的 lambda 中需要获取 y,所以就有了意想不到的堆分配,要想解决,可以将 y 定义为 const 或者 static 来避免这种不必要的分配开销,修改代码如下:

const int y = 1;
MyMethod(static x => x + y);

为了避免这种不必要和浪费内存的分配,可以在 lambda 上使用 static 关键词 及 变量上标注 const,值得注意的是,static 匿名函数不能访问封闭方法的局部变量和参数和 this 指针,但可以引用它的 静态方法 和 常量。

C#9 中使用静态匿名方法

先看一下例子:

    public class Demo
    {
        private string formattedText = "{0} It was developed by Microsoft's Anders Hejlsberg in the year 2000.";
        void DisplayText(Func<string, string> func)
        {
            Console.WriteLine(func("C# is a popular programming language."));
        }
        public void Display()
        {
            DisplayText(text => string.Format(formattedText, text));
            Console.Read();
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            new Demo().Display();
            Console.Read();
        }
    }

上面的例子中,formattedText变量会被 DisplayText 方法中的 func 所捕获,这也就意味着它会产生你意料之外的内存分配,把程序跑起来之后,会看到如下的输出。

为了避免这种内存分配,你只需要做两件事。

  • formattedText 上标记 const。
  • lambda 上标记 static。

所以修改后的代码如下:

    public class Demo
    {
        private const string formattedText = "{0} It was developed by Microsoft's Anders Hejlsberg in the year 2000.";
        void DisplayText(Func<string, string> func)
        {
            Console.WriteLine(func("C# is a popular programming language."));
        }
        public void Display()
        {
            DisplayText(static text => string.Format(formattedText, text));
            Console.Read();
        }
    }

现在就没有任何你意料之外的分配了,我想这也是你想要的。

现在你可以使用 static + const 组合来提升应用程序性能了,同时也可以有效的阻止在 lambda 中误用封闭方法中的局部变量和参数引发的不必要开销。

以上就是如何在C#9中使用static匿名函数的详细内容,更多关于C#9 中使用static匿名函数的资料请关注我们其它相关文章!

(0)

相关推荐

  • 使用C#9中records作为强类型ID的实例教程

    强类型ID 实体通常是整数,GUID或者string类型,因为数据库直接支持这些类型,但是,如果实体的ID的类型是一样的,比如都是整数的ID,这有可能会出现ID值传错的问题,看下边的示例. public void AddProductToOrder(int orderId, int productId, int count) { ... } ... // 这个地方,参数传错了 AddProductToOrder(productId, orderId, int count); 上面的代码可以很好地

  • C#9新特性init only setter的使用

    C# 9 中新支持了 init 关键字,这是一个特殊的 setter,用来指定只能在对象初始化的时候进行赋值,另外支持构造器简化的写法,比如:Target-typed new expression 在已知类型的情况下可以使用 new() 来代表构造方法的简化用法,可以简化字段的声明,也可以简化一次声明多个相同类型的变量 Sample 来看一个示例,我们定义一个测试用的 Person 类,测试代码如下: public class Person { public int Age { get; ini

  • C#9新特性之增强的模式匹配

    Intro C# 9 中进一步增强了模式匹配的用法,使得模式匹配更为强大,我们一起来了解一下吧 Sample C# 9 中增强了模式匹配的用法,增加了 and / or / not 操作符,而且可以直接判断属性,来看一下下面的这个示例: var person = new Person(); // or // string.IsNullOrEmpty(person.Description) if (person.Description is null or { Length: 0 }) { Con

  • 利用C#9.0新语法如何提升if语句美感

    前言 C# 语言一贯秉承简洁优美的宗旨,每次升级都会带来一些语法糖,让我们可以使代码变得更简洁.本文分享两个使用 C# 9.0 提升 if 语句美感的技巧示例. 使用属性模式代替 IsNullOrEmpty 在任何你使用 IsNullOrEmpty 的时候,可以考虑这样替换: string? hello = "hello world"; hello = null; // 旧的方式 if (!string.IsNullOrEmpty(hello)) { Console.WriteLine

  • 如何在C#9 中使用顶级程序 (top-level)

    当我们用 C# 进行编码的时候,总需要写很多的模板代码,即使是最简单的 console 程序,想象一下,如果去测试一个 类库 或者 API 的功能,通常你会用 Console 程序去实现,在开始工作的时候会发现你受到了 C# 标准模板的限制,业务逻辑必须要写在 Main 里,如下代码所示:     class Program     {         static void Main(string[] args)         {             //todo         }  

  • 浅谈C#9.0新特性之参数非空检查简化

    参数非空检查是缩写类库很常见的操作,在一个方法中要求参数不能为空,否则抛出相应的异常.比如: public static string HashPassword(string password) { if(password is null) { throw new ArgumentNullException(nameof(password)); } ... } 当异常发生时,调用者很容易知道是什么问题.如果不加这个检查,可能就会由系统抛出未将对象引用为实例之类的错误,这不利于调用者诊断错误. 由

  • C#9.0:Init相关总结

    背景 在以前的C#版本里面,如果需要定义一个不可修改的的类型的做法一般是:声明为readonly,并设置为只包含get访问器,不包含set访问器.如下: public class PersonInfo { /// <summary> /// 身份编号 /// </summary> public string UserCode { get; } /// <summary> /// 姓名 /// </summary> public string UserName

  • 深入谈谈C#9新特性的实际运用

    前言 你一定会好奇:"老周,你去哪开飞机了?这么久没写博客了." 老周:"我买不起飞机,开了个铁矿,挖了一年半的石头.谁知铁矿垮了,压死了几条蜈蚣,什么也没挖着." 所以,这么丢死人的事,还是不要提了,爷爷从小教导我做人要低调-- 一转眼,.NET 5 要来了,同时也带来了 C# 9.遥想当年,老周刚接触 .NET 1.1 的时候,才刚上大学:如今已经过去13年了.岁月是把水果刀,从来不饶人啊. 老周很少去写诸如"XXX新特性"之类的文章,总觉得

  • C#9.0新特性详解——顶级程序语句(Top-Level Programs)

    1 背景与动机 通常,如果只想用C#在控制台上打印一行"Hello World!",这可不是Console.WriteLine("Hello World!");一条语句就可以搞定的,还涉及到其他必要基础代码(如定义类和入口函数Main),例如下面: using System; class Program { static void Main() { Console.WriteLine("Hello World!"); } } 就打印一句"

  • C#9.0 新特性简介

    CandidateFeaturesForCSharp9 看到标题,是不是认为我把标题写错了?是的,C# 8.0还未正式发布,在官网它的最新版本还是Preview 5,通往C#9的漫长道路却已经开始.前写天收到了活跃在C#一线的BASSAM ALUGILI给我分享C# 9.0新特性,我在他文章的基础上进行翻译,希望能对大家有所帮助. 这是世界上第一篇关于C#9候选功能的文章.阅读完本文后,你将会为未来可能遇到的C# 9.0新特性做好更充分的准备. 这篇文章基于, C# 9.0候选新特性 原生大小的

  • C#9.0主要特性的一些想法

    前言 翻译自 Mads Torgersen 2020年5月20日的博文<Welcome to C# 9.0>,Mads Torgersen 是微软 C# 语言的首席设计师,也是微软 .NET 团队的项目群经理. C# 9.0 正在成形,我想和大家分享一下我们对下一版本语言中添加的一些主要特性的想法. 对于 C# 的每一个新版本,我们都在努力让常见编码场景的实现变得更加清晰和简单,C# 9.0 也不例外.这次特别关注的是支持数据模型的简洁和不可变表示. 就让我们一探究竟吧! 一.仅初始化(ini

随机推荐