SlideShare uma empresa Scribd logo
1 de 18
Baixar para ler offline
浅析延迟执行,[object Object],实现,优点,陷阱以及题外话,[object Object]
背景,[object Object],假设一个场景: 我们需要获取并遍历一个包含大量元素的序列,从中找出我们需要的某个元素。,[object Object],在此为了简单起见,我们假设该序列包含1000万个int值,我们需要找到的是100万这个值。,[object Object]
第一类实现方式:使用已有类型,[object Object],要从一个序列中过滤出一个值则首先需要生成这个序列。在此我们随意挑选三个序列类型:,[object Object],int[],[object Object],Collection<int>,[object Object],List<int>,[object Object]
第二种方式:延迟执行,[object Object],要实现延迟执行(Deferred Execution)有两种方式可选:,[object Object],自己创建实现了IEnumerable<T>接口的类型,[object Object],使用yield关键字,[object Object],这两种方式具体是如何实现延迟执行的?我们稍后根据代码讲解。,[object Object]
实现(1),[object Object],第一种方式中的三个已有类型的实现都相当简单,请看代码。,[object Object],生成数组的代码:,[object Object],生成Collection<int>的代码:,[object Object]
实现(1),[object Object],生成List<int>的代码:,[object Object]
实现(2),[object Object],自己创建实现了IEnumerable<T>的类型的方式是最复杂,最难写的。这个方式的基本思路就是构造一个状态机,由于要在多个状态之间做切换,所以很容易出错。请看代码:,[object Object],由于代码过长,在此只给出代码结构图。这个类型同时实现了IEnumerable<T>和IEnumerator<T>两个接口。其MoveNext方法和Current属性每被调用一次时,才即时生成一个元素,这样就避免了一次性填充整个序列,从而实现了延迟执行。,[object Object]
实现(3),[object Object],使用yield关键字是最简单,最偷懒的方式。,[object Object],实际上,yield背后对应的实现和我们讲到的上一种方式基本是一样的。编译器会把包含yield的代码块构造成一个同时实现了IEnumerable<T>和IEnumerator<T>的类型。,[object Object]
测试(1),[object Object],测试中有几个辅助方法(TestTime,IterateSequence和TestSpeed)需要简单说明,请看代码:,[object Object],TestTime的代码:,[object Object],TestTime接受一个Action类型的参数,在方法体内执行action并为其计时,最后输出所耗时间。,[object Object]
测试(1),[object Object],IterateSequence的代码:,[object Object],这段代码很简单:迭代一个序列,当找到要找的值之后则break出去。,[object Object]
测试(1),[object Object],TestSpeed的代码:,[object Object],这段代码测试所有五种实现方式的效率。把创建序列和过滤序列的代码包裹在lambda表达式中传入TestTime。,[object Object]
测试(2),[object Object],从1000万个元素中筛选,[object Object],从1亿个元素中筛选,[object Object],可以发现,当序列中元素数量增加时,前三种实现方式的耗时量都在呈线性增长。,[object Object],而后两种实现方式的耗时量则基本没有变化。,[object Object]
总结(1):延迟执行的好处,[object Object],从前面的测试结果中可以看出,延迟执行的最明显的优势即在于不会立即创建整个序列,而是在调用方索取时才即时生成元素。,[object Object],这也正好解释了为什么将序列容量从1000万增加为1亿时延迟执行的方式执行时间基本不变。因为延迟执行的方法总是只生成100万个元素而已。,[object Object]
总结(2):可能的陷阱,[object Object],由于用来生成序列的算法被封装在了状态机内,所以每次用foreach迭代这个序列时,整个序列都会被重新生成一次。,[object Object],如果需要避免这种行为,可以通过在延迟执行的返回结果上调用ToArray()或ToList()。然后在每次迭代中都使用已经填充好的Array或List。,[object Object],其实这种特性在有的场景下是很有益的,比如生成序列的算法依赖于某些外部的变化条件(数据库,网络数据或者系统时间)。,[object Object]
题外话(1):foreach,[object Object],我们每天都会用到的foreach究竟是如何实现的呢?,[object Object],可以看出,一个foreach的“空转”循环基本等价于一个while循环加一个try/finally代码块。,[object Object],请注意在finally代码块中调用了Dispose方法。如果这个foreach作用于一个延迟执行方法的返回值上,那么对Dispose的调用就相当于把状态机的状态清零。,[object Object]
题外话(2):序列的重新生成,[object Object],前面讲foreach的题外话其实是为了讲解序列的重新生成做基础。,[object Object],前面已经讲过,foreach的尾部会调用迭代器的Dispose方法,把状态机的状态清零。这样,如果有下一个foreach来迭代同一个序列的话,则会将封装在状态机内的生成元素的算法重新执行一遍,也就相当于重新生成了整个序列。,[object Object],这样说或许过于晦涩,请看下一页的图解。,[object Object]
题外话(2):序列的重新生成,[object Object],请看这把春田步枪,你装入子弹(调用GetEnumerator),撞针顶住了第一颗子弹(第一次调用MoveNext),开枪(访问Current属性),然后撞针顶住下一颗子弹(又一次调用MoveNext),反复开枪(反复调用MoveNext并访问Current属性),直到子弹耗尽(MoveNext返回了false),枪膛打开了(调用了Dispose)。然后再装入子弹开始下一轮的射击(序列的重新生成)。,[object Object]
谢谢,[object Object]

Mais conteúdo relacionado

Mais procurados

12, string
12, string12, string
12, stringted-xu
 
C python 原始碼解析 投影片
C python 原始碼解析 投影片C python 原始碼解析 投影片
C python 原始碼解析 投影片kao kuo-tung
 
C++基礎程式設計 ch5 陣列
C++基礎程式設計 ch5 陣列C++基礎程式設計 ch5 陣列
C++基礎程式設計 ch5 陣列requiemformemories
 
C++基礎程式設計 ch2 變數與運算子
C++基礎程式設計 ch2 變數與運算子C++基礎程式設計 ch2 變數與運算子
C++基礎程式設計 ch2 變數與運算子requiemformemories
 
Swift 程序语言介绍
Swift 程序语言介绍Swift 程序语言介绍
Swift 程序语言介绍明 李
 
C++基礎程式設計 ch3 條件判斷
C++基礎程式設計 ch3 條件判斷C++基礎程式設計 ch3 條件判斷
C++基礎程式設計 ch3 條件判斷requiemformemories
 
Lesson 2 Basicstructure
Lesson 2 BasicstructureLesson 2 Basicstructure
Lesson 2 BasicstructureRyan Chung
 
Javascript 培训第三节 基础下
Javascript 培训第三节 基础下Javascript 培训第三节 基础下
Javascript 培训第三节 基础下liziqi7
 
Javascript oop-o52tiger
Javascript oop-o52tigerJavascript oop-o52tiger
Javascript oop-o52tigero52tiger
 

Mais procurados (12)

12, string
12, string12, string
12, string
 
關於Import
關於Import關於Import
關於Import
 
C python 原始碼解析 投影片
C python 原始碼解析 投影片C python 原始碼解析 投影片
C python 原始碼解析 投影片
 
C++基礎程式設計 ch5 陣列
C++基礎程式設計 ch5 陣列C++基礎程式設計 ch5 陣列
C++基礎程式設計 ch5 陣列
 
C++基礎程式設計 ch2 變數與運算子
C++基礎程式設計 ch2 變數與運算子C++基礎程式設計 ch2 變數與運算子
C++基礎程式設計 ch2 變數與運算子
 
Swift 程序语言介绍
Swift 程序语言介绍Swift 程序语言介绍
Swift 程序语言介绍
 
C++基礎程式設計 ch3 條件判斷
C++基礎程式設計 ch3 條件判斷C++基礎程式設計 ch3 條件判斷
C++基礎程式設計 ch3 條件判斷
 
Lesson 2 Basicstructure
Lesson 2 BasicstructureLesson 2 Basicstructure
Lesson 2 Basicstructure
 
C語言結構與串列
C語言結構與串列 C語言結構與串列
C語言結構與串列
 
Javascript 培训第三节 基础下
Javascript 培训第三节 基础下Javascript 培训第三节 基础下
Javascript 培训第三节 基础下
 
SCJP ch18
SCJP ch18SCJP ch18
SCJP ch18
 
Javascript oop-o52tiger
Javascript oop-o52tigerJavascript oop-o52tiger
Javascript oop-o52tiger
 

Destaque

Web 2.0 vodcast
Web 2.0 vodcastWeb 2.0 vodcast
Web 2.0 vodcastonebel
 
Khn werkconf-duurzamebinnenstad-120124
Khn werkconf-duurzamebinnenstad-120124Khn werkconf-duurzamebinnenstad-120124
Khn werkconf-duurzamebinnenstad-120124Hermannus Stegeman
 
Pragmatic+unit+testing+in+c%23+with+n unit%2 c+second+edition
Pragmatic+unit+testing+in+c%23+with+n unit%2 c+second+editionPragmatic+unit+testing+in+c%23+with+n unit%2 c+second+edition
Pragmatic+unit+testing+in+c%23+with+n unit%2 c+second+editioncuipengfei
 
3 Things Every Sales Team Needs to Be Thinking About in 2017
3 Things Every Sales Team Needs to Be Thinking About in 20173 Things Every Sales Team Needs to Be Thinking About in 2017
3 Things Every Sales Team Needs to Be Thinking About in 2017Drift
 
How to Become a Thought Leader in Your Niche
How to Become a Thought Leader in Your NicheHow to Become a Thought Leader in Your Niche
How to Become a Thought Leader in Your NicheLeslie Samuel
 

Destaque (6)

Texel 120115
Texel 120115Texel 120115
Texel 120115
 
Web 2.0 vodcast
Web 2.0 vodcastWeb 2.0 vodcast
Web 2.0 vodcast
 
Khn werkconf-duurzamebinnenstad-120124
Khn werkconf-duurzamebinnenstad-120124Khn werkconf-duurzamebinnenstad-120124
Khn werkconf-duurzamebinnenstad-120124
 
Pragmatic+unit+testing+in+c%23+with+n unit%2 c+second+edition
Pragmatic+unit+testing+in+c%23+with+n unit%2 c+second+editionPragmatic+unit+testing+in+c%23+with+n unit%2 c+second+edition
Pragmatic+unit+testing+in+c%23+with+n unit%2 c+second+edition
 
3 Things Every Sales Team Needs to Be Thinking About in 2017
3 Things Every Sales Team Needs to Be Thinking About in 20173 Things Every Sales Team Needs to Be Thinking About in 2017
3 Things Every Sales Team Needs to Be Thinking About in 2017
 
How to Become a Thought Leader in Your Niche
How to Become a Thought Leader in Your NicheHow to Become a Thought Leader in Your Niche
How to Become a Thought Leader in Your Niche
 

Deferred execution

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.