C#函数式编程中的惰性求值详解

 更新时间:2015年01月28日 10:50:48   投稿:junjie  
这篇文章主要介绍了C#函数式编程中的惰性求值详解,本文讲解了惰性求值的相关知识并给出代码实例,需要的朋友可以参考下

惰性求值

      在开始介绍今天要讲的知识之前,我们想要理解严格求值策略和非严格求值策略之间的区别,这样我们才能够深有体会的明白为什么需要利用这个技术。首先需要说明的是C#语言小部分采用了非严格求值策略,大部分还是严格求值策略。首先我们先演示非严格求值策略的情况,我们先在控制台项目中写一个DoOneThing方法。

然后在Main方法中写入下面这串代码:

       然后我们运行程序,会发现DoOneThing方法并没有执行。当然这看起来也很正常,因为这是或,并且第一个已经是true了。整个表达式就是true了,自然第二个就无需求值了。但是这恰恰就是非严格求值的策略,如果是严格求值策略的话整个表达式都会计算。接着就是严格求值策略的情况了,这个相信很多人都会立马明白,首先我们需要再写一个DoSomeThing方法:

接着修改Main方法:

执行之后我们可以看到如下的结果:

       但是我们可以清楚的看到a的值是false,根本不会使用b值,但是传递参数的时候已经将DoOneThing方法执行并赋值给b,假设这个方法是一个非常耗时的操作。那么我们就会白白浪费掉这段时间,最后求得的值也没有使用的到。而这正是严格求值策略,而今天的主要目标就是改变这种情况,能够在我们确定需要某个值的时候才计算。下面我们就可以开始改造这个方法,让其能够支持惰性求值。首先我们修改DoSomeThing方法:

      这里我们将参数类型都改成了函数,这样将要传递进来的参数都改变成函数。只有在我们需要的时候才执行求值,否则是不会运行的,对应的Main方法中我们需要按照如下方式修改:

      这里我们并不需要把DoOneThing方法的返回类型改掉,如果这样的话。在现有项目上使用函数式编程就会显得太麻烦了。这里我们仅仅只需要利用匿名函数就可以办到了,下面我们可以看最后的执行效果:

       DoOneThing方法并没有执行,因为DoSomeThing中根本没有确定使用这个变量,这样我们就能够节省下这部分计算的时间,但是事实上我们还没有结束,实际的开发中我们可能需要多次使用这个值,比如下面我们修改DoSomeThing方法:

并且在Main方法中调用DoSomeThing方法时将第一个参数改成true,然后执行我们就可以看到下面的输出结果:

 DoOneThing方法被执行了两次,当然我们可以利用局部变量保存,可能你会这么写:

      如果这么写,那么我们的惰性求值就没有任何意义了,因为一进入这个方法就执行了这个方法,跟传递参数时直接将运算后的结果赋值给b没有任何区别了。当然也有其他一些技巧可以避免,但是这些技巧可不是下面要讲的内容,我们可以将其封装起来,比如我们可以写个LazyS<T>类:

      我们可以看到在构造方法部分我们将对应的函数作为参数接收并保存到function中,只有再调用Value时候会执行该函数并将值保存,并且在下次调用时,如果已经求值过则直接返回缓存过的值,这样就能够避免重复的执行了,对应的我们还要修改DoSomeThing方法和Main方法:

最终执行后我们可以看到仅执行了一次DoOneThing方法:

       一些读者可能为问为什么类名不要Lazy而是加个S,因为.net中已经为我们包含了Lazy<T>类,相信很多人基本上从没有用过。只知道Func和Action的存在,下面我们修改我们的代码直接利用自带的:

最终的结果之前的是一摸一样,当然系统自带的Lazy功能更多,并且支持多线程。

 就到这里为止吧,周五了大家已经按耐不住了,写了太多可能就没有心思往下看了,所以将这些全部一个一个拆分开来细讲。

相关文章

  • Unity shader实现移动端模拟深度水效果

    Unity shader实现移动端模拟深度水效果

    这篇文章主要为大家详细介绍了Unity shader实现移动端模拟深度水效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-05-05
  • C#目录和文件管理操作详解

    C#目录和文件管理操作详解

    在C#中常用的目录操作类有Directory,DirectoryInfo,下面这篇文章主要给大家介绍了关于C#目录和文件管理操作的相关资料,需要的朋友可以参考下
    2022-10-10
  • c#调用c++的DLL的实现方法

    c#调用c++的DLL的实现方法

    本文主要介绍了c#调用c++的DLL的实现方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-05-05
  • WinForm防止程序重复运行的方法分析

    WinForm防止程序重复运行的方法分析

    这篇文章主要介绍了WinForm防止程序重复运行的方法,通过记录窗口句柄实现防止WinForm程序重复运行的功能,需要的朋友可以参考下
    2017-05-05
  • 深入分析WPF客户端读取高清图片卡以及缩略图的解决方法详解

    深入分析WPF客户端读取高清图片卡以及缩略图的解决方法详解

    本篇文章是对WPF客户端读取高清图片卡以及缩略图的解决方法进行了详细的分析介绍,需要的朋友参考下
    2013-05-05
  • C#配置文件设置及应用详解

    C#配置文件设置及应用详解

    在软件开发过程中,配置文件是常用的一个功能,用于在程序运行时调整应用程序的行为,C# 提供了多种方式来创建和使用配置文件,本文将详细介绍 C# 配置文件的创建、修改、读取和写入,以及跨平台配置文件的应用,需要的朋友可以参考下
    2024-06-06
  • 浅析C#更改令牌ChangeToken

    浅析C#更改令牌ChangeToken

    这篇文章主要介绍了C#更改令牌ChangeToken,文中运用大量代码讲解的非常详细,感兴趣的小伙伴一起来看看这篇文章吧
    2021-09-09
  • C#结合AForge实现摄像头录像

    C#结合AForge实现摄像头录像

    最近由于兴趣学习了下在C#上使用AForge录制摄像头视频并压缩编码。总体上来说这个第三方.net视觉开发库还是比较稳定的
    2017-09-09
  • C#在Entity Framework中实现事务回滚

    C#在Entity Framework中实现事务回滚

    这篇文章介绍了C#在Entity Framework中实现事务回滚的方法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-08-08
  • C#实现数据包加密与解密实例详解

    C#实现数据包加密与解密实例详解

    这篇文章主要介绍了C#实现数据包加密与解密的方法,是一项很实用的技能,需要的朋友可以参考下
    2014-07-07

最新评论