要了解迭代器是干什么的,首先要了解为什么要用迭代
使用foreach的条件是可枚举集合,如果不是,会报错,所以要实现IEnumerable接口,使得可以使用foreach,但为了减轻程序员的工作量,提供了迭代器来完成工作。
以下代码只有加粗部分工作。
IEnumerator IEnumerable.GetEnumerator()
{
//通过手写枚举类型实现
// return new TreeEnumerator(this);
throw new NotImplementedException();
/* //通过迭代器来实现枚举
if (this.LeftTree != null)
{
foreach (TItem item in this.LeftTree)
{
yield return item;
}
}
yield return this.NodeData;
if (this.RightTree != null)
{
foreach (TItem item in this.RightTree )
{
yield return item ;
}
}
*/
}
调用代码为如下,目的是为了循环输出一个int型树的集合
Tree<int> tree1 = new Tree<int>(10);
tree1.Insert(2);
tree1.Insert(4);
tree1.Insert(222);
foreach (int item in tree1)
{
Console.WriteLine(item);
}
![这里写图片描述](https://img-blog.csdn.net/20170609195119891?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvU3cxMzE2OTY0MjYyMw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
结果是报错了。
自己写一个枚举型,如下
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BinaryTree
{
class TreeEnumerator:IEnumerator where TItem :IComparable
{
private Tree currentData = null;
private TItem currentItem = default(TItem);
private Queue enumData = null;
public TreeEnumerator(Tree data)
{
this.currentData = data;
}
private void populate(Queue enumQuene, Tree tree)
{
if (tree.LeftTree != null)
{
populate(enumQuene, tree.LeftTree);
}
enumQuene.Enqueue(tree.NodeData );
if (tree.RightTree != null)
{
populate(enumQuene, tree.RightTree);
}
}
TItem IEnumerator<TItem>.Current
{
get {
if (this.enumData == null)
{
throw new InvalidOperationException("Use MoveNext before calling Current");
}
return this.currentItem;
}
}
void IDisposable.Dispose()
{
// throw new NotImplementedException();
}
object System.Collections.IEnumerator.Current
{
get
{
throw new NotImplementedException();
}
}
bool System.Collections.IEnumerator.MoveNext()
{
if (this.enumData == null)
{
this.enumData = new Queue<TItem>();
populate(this.enumData, this.currentData);
}
if (this.enumData.Count > 0)
{
this.currentItem = this.enumData.Dequeue();
return true;
}
return false;
}
void System.Collections.IEnumerator.Reset()
{
throw new NotImplementedException();
}
}
}
结果是可以运行的
但是看上图很明显这是一个很麻烦的工作,所以有了迭代器来减轻程序员的负担。以 yield关键字来解决问题。
if (this.LeftTree != null)
{
foreach (TItem item in this.LeftTree)
{
yield return item;
}
}
yield return this.NodeData;
if (this.RightTree != null)
{
foreach (TItem item in this.RightTree )
{
yield return item ;
}
每一次运行到yield,程序都会把结果送出去,并等待下一次调用这程序,下一次调用时会接着上一次调用的结果。
![这里写图片描述](https://img-blog.csdn.net/20170609195850217?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvU3cxMzE2OTY0MjYyMw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
结果和自己写的一样,但实现过程被大大简化了。
最后附上树的代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BinaryTree
{
public class Tree:IEnumerable where TItem :IComparable
{
public TItem NodeData { get; set; }
public Tree LeftTree { get; set; }
public Tree RightTree { get; set; }
public Tree(TItem nodeValue)
{
this.NodeData = nodeValue;
this.LeftTree = null;
this.RightTree = null;
}
public void Insert(TItem newItem)
{
//插入一个数据项,如果大于当前值,插入左侧,否则插入右侧
TItem currentNodeValue = this.NodeData;
if (currentNodeValue.CompareTo(newItem) > 0)
{
if (this.LeftTree == null)
{
this.LeftTree = new Tree(newItem);
}
else
{
this.LeftTree.Insert(newItem);
}
}
else
{
if (this.RightTree == null)
{
this.RightTree = new Tree<TItem>(newItem);
}
else
{
this.RightTree.Insert(newItem);
}
}
}
public String WalkTree()
{
//历遍Tree
String result = "";
if (this.LeftTree != null)
{
result = this.LeftTree.WalkTree()+" ";
}
result += String.Format("{0}", this.NodeData.ToString())+" ";
if (this.RightTree != null)
{
result += this.RightTree.WalkTree()+" ";
}
return result;
}
IEnumerator<TItem> IEnumerable<TItem>.GetEnumerator()
{
//通过手写枚举类型实现
// return new TreeEnumerator<TItem>(this);
//throw new NotImplementedException();
//通过迭代器来实现枚举
if (this.LeftTree != null)
{
foreach (TItem item in this.LeftTree)
{
yield return item;
}
}
yield return this.NodeData;
if (this.RightTree != null)
{
foreach (TItem item in this.RightTree )
{
yield return item ;
}
}
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
throw new NotImplementedException();
}
}
}