[CSharp In Depth]迭代器
2014-03-08 17:35
351 查看
最近好多事请,好多事情都反反复复,这样的结果就是给人很大的挫败感。从今以后,做什么事一定要有头有尾,坚持完成!
除了集合类型可以使用Foreach,其他的内容也可以使用Foreach来遍历,使用Foreach保证了类型统一安全,代码简洁高效。
要想使用Foreach的语法规则进行遍历,只需要实现IEnumberable<T>接口,而该接口的实现就是要实现IEnumerator<T>,在C#2中已经引入的yield return完美的解决了这个问题。
这是最简单的样子。
做一点有意思的工作,比如按行来编译文件呢?
考虑将reader对象作为形参传入,其实是引入了更大的问题:我们需要实现的仅仅是一个需要是就用用的迭代器!如果作为形参,那么每次调用都要用户负责对象的清理工作,甚至在第一调用之前出现了异常,可能出现无法清理的问题。同时,这样的设计还会导致每次获得的都是相同的IEnumerator。解决思路来源于:一个迭代器的代码段的真正执行是要到第一次MoveNext的,所以,实现迭代器的时候,形参可以“暂时为null"(当然更多的是理解上的,因为实现了迭代器在使用的时候形参必须是可以读取的),而接口有类似的功能,而且这里需要的功能是返回一个对象,那么就跟委托有点类似,委托太方便了,特别是匿名委托,特别是公共定义的匿名委托,只是返回一个对象,那么刚刚可以使用Func<out
TResult>,
由于形参采用的是Func<out TResult>,且委托里面有一个外部变量捕获的特征,那么用一个方法包装一下,就可以传入外部的一些信息了
如果再对必须传入一个Encoding不爽,那么可以使用重载搞个常用的方法
小结: 1 委托在功能上可以代替只有一个方法的接口
2 匿名方法的外部变量捕获方便。
3 实现了IEnumerable<T>就可以方便的遍历了。
除了集合类型可以使用Foreach,其他的内容也可以使用Foreach来遍历,使用Foreach保证了类型统一安全,代码简洁高效。
要想使用Foreach的语法规则进行遍历,只需要实现IEnumberable<T>接口,而该接口的实现就是要实现IEnumerator<T>,在C#2中已经引入的yield return完美的解决了这个问题。
IEnumerable<int> GetEnumerable() { for (int i = 0; i < 10; i++) yield return i; }
这是最简单的样子。
做一点有意思的工作,比如按行来编译文件呢?
IEnumerable<string> GetEnumerable(string filename) { using(TextReader reader = File.OpenText(filename)) { string line; while ((line = reader.ReadLine()) != null) { yield return line; } } }这样实现用一次没有什么问题,但是从设计的角度来看,reader的控制权和生命周期均被透明化了,而且只是支持一个txt文件,如果考虑一个网络的文本呢,进行改进:
考虑将reader对象作为形参传入,其实是引入了更大的问题:我们需要实现的仅仅是一个需要是就用用的迭代器!如果作为形参,那么每次调用都要用户负责对象的清理工作,甚至在第一调用之前出现了异常,可能出现无法清理的问题。同时,这样的设计还会导致每次获得的都是相同的IEnumerator。解决思路来源于:一个迭代器的代码段的真正执行是要到第一次MoveNext的,所以,实现迭代器的时候,形参可以“暂时为null"(当然更多的是理解上的,因为实现了迭代器在使用的时候形参必须是可以读取的),而接口有类似的功能,而且这里需要的功能是返回一个对象,那么就跟委托有点类似,委托太方便了,特别是匿名委托,特别是公共定义的匿名委托,只是返回一个对象,那么刚刚可以使用Func<out
TResult>,
private static IEnumerable<string> GetFileReaderEnumerable(Func<StreamReader> reader) { //考虑委托类型如何运行,枚举的好处来了:执行时才真正返回一个reader对象 using(TextReader textReader = reader()) { string line; while((line = textReader.ReadLine()) != null) { yield return line; } } }
由于形参采用的是Func<out TResult>,且委托里面有一个外部变量捕获的特征,那么用一个方法包装一下,就可以传入外部的一些信息了
static IEnumerable<string> ReadLines(string filename, Encoding fileencodeing) { return GetFileReaderEnumerable(delegate { return new StreamReader(filename, fileencodeing); }); } public static void ReadAllData() { string filename = Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, @"testdata.txt"); if (File.Exists(filename)) { IEnumerable<string> datalist = ReadLines(filename); foreach (string line in datalist) { Console.WriteLine(line); } } }
如果再对必须传入一个Encoding不爽,那么可以使用重载搞个常用的方法
static IEnumerable<string> ReadLines(string filename) { return ReadLines(filename, Encoding.UTF8); }
小结: 1 委托在功能上可以代替只有一个方法的接口
2 匿名方法的外部变量捕获方便。
3 实现了IEnumerable<T>就可以方便的遍历了。
相关文章推荐
- 《C# in Depth:深入理解C#》读书笔记 - 迭代器
- C# in depth (第六章 实现迭代器的捷径)
- 月经贴 】 Csharp in depth
- csharp:using Newtonsoft.Json.Net2.0 in .net 2.0 webform
- Deferences between String and string in C sharp
- MVVM in Depth
- Alternating row colors in a Flex Tree control using the depthColors style
- 巩固基础知识,从C# in depth开始
- WCF Addressing In Depth Note
- C# in Depth
- 光照贴图深入学习 Lightmapping In-Depth
- Singleton Pattern in CSharp
- C# in depth ( 第四章 可空类型)
- Templates in depth(Chapter 3 of Thinking in C++ Vol 2)
- userCSharp namespace in map
- [Javascript] JavaScript Array Methods in Depth - push
- elasticsearch---search in depth之multi-field search
- csharp:using Newtonsoft.Json.Net2.0 in .net 2.0 webform
- Sequence of shopping carts in-depth analysis with R(1)
- 【C# in depth 第三版】温故而知新(1)