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功能更多,并且支持多线程。

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

相关文章

  • 基于C# 写一个 Redis 数据同步小工具

    基于C# 写一个 Redis 数据同步小工具

    Redis支持主从同步。数据可以从主服务器向任意数量的从服务器上同步,从服务器可以是关联其他从服务器的主服务器。这篇文章主要介绍了用 C# 写一个 Redis 数据同步小工具,需要的朋友可以参考下
    2020-02-02
  • C# 合并GriewView相同列的小例子

    C# 合并GriewView相同列的小例子

    C# 合并GriewView相同列的小例子,需要的朋友可以参考一下
    2013-03-03
  • C#解析json字符串总是多出双引号的原因分析及解决办法

    C#解析json字符串总是多出双引号的原因分析及解决办法

    json好久没用了,今天在用到json的时候,发现对字符串做解析的时候总是多出双引号,下面给大家介绍C#解析json字符串总是多出双引号的原因分析及解决办法,需要的朋友参考下吧
    2016-03-03
  • 基于Avalonia实现自定义弹窗的示例详解

    基于Avalonia实现自定义弹窗的示例详解

    对于使用avalonia的时候某些功能需要到一些提示,比如异常或者成功都需要对用户进行提示,所以需要单独实现弹窗功能,并且可以自定义内部组件,这一期将手动实现一个简单的小弹窗,并且很容易自定义,希望大家喜欢
    2023-02-02
  • C#实现异步的常用方式总结

    C#实现异步的常用方式总结

    这篇文章主要为大家详细介绍了C#实现异步的几个常用方式,文中的示例代码讲解详细,具有一定的学习价值,感兴趣的小伙伴可以了解一下
    2023-05-05
  • c#对xml增删改查操作示例

    c#对xml增删改查操作示例

    本文主要介绍c#对xml增删改查操作的示例,大家参考使用吧
    2014-01-01
  • Python设计模式编程中的备忘录模式与对象池模式示例

    Python设计模式编程中的备忘录模式与对象池模式示例

    这篇文章主要介绍了Python设计模式编程中的备忘录模式与对象池模式,文中分别举了表单和线程的相关示例,需要的朋友可以参考下
    2016-02-02
  • C#实现的调用DOS命令操作类实例

    C#实现的调用DOS命令操作类实例

    这篇文章主要介绍了C#实现的调用DOS命令操作类,实例分析了C#调用系统常用DOS命令的相关技巧,非常具有实用价值,需要的朋友可以参考下
    2015-04-04
  • C# 中使用NModbus4通信库执行写操作

    C# 中使用NModbus4通信库执行写操作

    在C#中NModbus4库提供了一个方便的方式来与支持Modbus协议的设备进行交互,本文就来介绍了使用NModbus4通信库执行写操作,具有一定的参考价值,感兴趣的可以了解一下
    2024-03-03
  • C#计算文件MD5校验的方法

    C#计算文件MD5校验的方法

    这篇文章主要介绍了C#计算文件MD5校验的方法,涉及C#针对文件进行md5校验的技巧,非常具有实用价值,需要的朋友可以参考下
    2015-04-04

最新评论