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

C#迭代器(Foreach)实现方法

2009-07-06 10:55 375 查看
一、为非泛型列表创建迭代器块
using System;
using System.Collections.Generic;
using System.Text;

namespace ForeachConstruct
{
/*
* 下面的代码示例阐释如何编写可与foreach 一起使用的非泛型集合类。
* 该类是字符串标记化拆分器,类似于C 运行时库函数strtok。
* 此示例描述的是只有在您无法使用泛型集合类时才采用的推荐做法。
* C# 语言和.NET Framework 的2.0 版和更高版本支持泛型。
* 在下面的示例中,Tokens 使用“”和“-”作为分隔符将句子“This is a sample sentence.-yang lei”
* 拆分为标记,并使用foreach 语句枚举这些标记:
*/

#region 省略接口
/*
* 在C# 中,集合类并非必须严格从IEnumerable 和IEnumerator 继承才能与foreach 兼容;
* 只要类有所需的GetEnumerator、MoveNext、Reset 和Current 成员,便可以与foreach 一起使用。
* 省略接口的好处为,使您可以将Current 的返回类型定义得比object 更明确,
* 从而提供了类型安全。
* 省略IEnumerable 和IEnumerator 的缺点是,
* 集合类不再能够与其他公共语言运行库兼容语言的foreach 语句或等效项交互操作
*/
/*
public class Tokens
{
private string[] elements;

public Tokens(string source, char[] delimiters)
{
elements = source.Split(delimiters);
}

#region IEnumerable 成员

public TokenEnumerator GetEnumerator()
{
return new TokenEnumerator(this);
}
#endregion

public class TokenEnumerator
{
private int position = -1;
private Tokens t;

public TokenEnumerator(Tokens t)
{
this.t = t;
}

#region IEnumerator 成员

public string Current
{
get
{
return t.elements[position];
}
}

public bool MoveNext()
{
if (position < t.elements.Length - 1)
{
position++;
return true;
}
else
{
return false;
}
}

public void Reset()
{
position = -1;
}

#endregion
}
}
*/
#endregion

#region 实现接口
/*
* 您可以同时拥有两者的优点,即C# 中的类型安全以及与其他公共语言运行库兼容语言的互操作性,
* 方法是从IEnumerable 和IEnumerator 继承并使用显式接口实现。
*/
public class Tokens : System.Collections.IEnumerable
{
private string[] elements;

public Tokens(string source, char[] delimiters)
{
elements = source.Split(delimiters);
}

#region IEnumerable 成员

public System.Collections.IEnumerator GetEnumerator()
{
return new TokenEnumerator(this);
}

#endregion

public class TokenEnumerator : System.Collections.IEnumerator
{
private int position = -1;
private Tokens t;

public TokenEnumerator(Tokens t)
{
this.t = t;
}

#region IEnumerator 成员

public object Current
{
get
{
return t.elements[position];
}
}

public bool MoveNext()
{
if (position < t.elements.Length - 1)
{
position++;
return true;
}
else
{
return false;
}
}

public void Reset()
{
position = -1;
}

#endregion
}
}
#endregion

class Program
{
static void Main(string[] args)
{
Tokens f = new Tokens("This is a sample sentence.-yang lei", new char[] { ' ', '-' });

foreach (string item in f)
{
System.Console.WriteLine(item);
}
}
}

/*
* 输出
This
is
a
sample
sentence.
yang
lei
请按任意键继续. . .
*/
}

二、为泛型列表创建迭代器块
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;

namespace ForeachConstruct
{
//为泛型列表创建迭代器块
public class Stack<T> : IEnumerable<T>
{
private T[] values = new T[100];
private int top = 0;

public void Push(T t)
{
values[top++] = t;
}

public T Pop()
{
return values[--top];
}

public IEnumerable<T> TopToBottom
{
get { return this; }
}

public IEnumerable<T> BottomToTop
{
get
{
for (int i = 0; i < top; i++)
{
yield return values[i];
}
}
}

public IEnumerable<T> TopN(int n)
{
int j = (n >= top) ? 0 : top - n;

for (int i = top; --i >= j; )
{
yield return values[i];
}
}

#region IEnumerable<T> 成员

public IEnumerator<T> GetEnumerator()
{
for (int i = top; --i >= 0; )
{
yield return values[i];
}
}

#endregion

#region IEnumerable 成员

IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}

#endregion
}

class Test
{
static void Main()
{
Stack<int> s = new Stack<int>();
for (int i = 0; i < 10; i++)
{
s.Push(i);
}

foreach (int n in s)
{
System.Console.Write("{0} ", n);
}
System.Console.WriteLine();

foreach (int n in s.TopToBottom)
{
System.Console.Write("{0} ", n);
}
System.Console.WriteLine();

foreach (int n in s.BottomToTop)
{
System.Console.Write("{0} ", n);
}
System.Console.WriteLine();

foreach (int n in s.TopN(7))
{
System.Console.Write("{0} ", n);
}
System.Console.WriteLine();
}
}

/*
* 输出
9 8 7 6 5 4 3 2 1 0
9 8 7 6 5 4 3 2 1 0
0 1 2 3 4 5 6 7 8 9
9 8 7 6 5 4 3
请按任意键继续. . .
*/

/* yield的说明
* 在迭代器块中用于向枚举数对象提供值或发出迭代结束信号。它的形式为下列之一:
yield return expression;
yield break;
*
参数
expression
进行计算并以枚举数对象值的形式返回。expression 必须可以隐式转换为迭代器的yield 类型。
*
备注
yield 语句只能出现在iterator 块中,该块可用作方法、运算符或访问器的体。
这类方法、运算符或访问器的体受以下约束的控制:
不允许不安全块。
方法、运算符或访问器的参数不能是ref 或out。
yield 语句不能出现在匿名方法中。
当和expression 一起使用时,yield return 语句不能出现在catch 块中或含有一个或多个catch 子句的try 块中。
*
包含yield语句的方法或属性称为迭代块。迭代块必须声明为返回IEnumerator或IEnumerable接口.
yield语句从本质上讲是运用了延迟计算(Lazy evaluation或delayed evaluation)的思想。
在Wiki上可以找到延迟计算的解释:将计算延迟,直到需要这个计算的结果的时候才计算,
这样就可以因为避免一些不必要的计算而改进性能,在合成一些表达式时候还可以避免一些不必要的条件,
因为这个时候其他计算都已经完成了,所有的条件都已经明确了,有的根本不可达的条件可以不用管了。
*/

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: