您的位置:首页 > 编程语言 > C#

[CSharp In Depth]迭代器

2014-03-08 17:35 351 查看
最近好多事请,好多事情都反反复复,这样的结果就是给人很大的挫败感。从今以后,做什么事一定要有头有尾,坚持完成!

除了集合类型可以使用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>就可以方便的遍历了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: