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上可以找到延迟计算的解释:将计算延迟,直到需要这个计算的结果的时候才计算,
这样就可以因为避免一些不必要的计算而改进性能,在合成一些表达式时候还可以避免一些不必要的条件,
因为这个时候其他计算都已经完成了,所有的条件都已经明确了,有的根本不可达的条件可以不用管了。
*/
}
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上可以找到延迟计算的解释:将计算延迟,直到需要这个计算的结果的时候才计算,
这样就可以因为避免一些不必要的计算而改进性能,在合成一些表达式时候还可以避免一些不必要的条件,
因为这个时候其他计算都已经完成了,所有的条件都已经明确了,有的根本不可达的条件可以不用管了。
*/
}
相关文章推荐
- 能用foreach遍历访问的对象需要实现____接口或声明____方法的类型
- C#使用yield关键字让自定义集合实现foreach遍历的方法
- C# 通过接口IEnumerator让自己编写的对象/类,实现foreach遍历方法
- ECMA5数组的新增方法有哪些及forEach()模仿实现
- 简单标签实现foreach代码和jar打包的两种方法
- 简单标签实现foreach代码和jar打包的方法
- foreach 仅需要类实现public IEnumerator GetEnumerator()方法而无需实现接口
- php中foreach结合curl实现多线程的方法分析
- 能用foreach遍历访问的对象需要实现 ________________接口或声明________________方法的类型。
- c++中foreach的一种实现方法
- 合理使用“.NET扩展方法”来简化代码(例子:空值判断,利用扩展方法实现LINQ操作符ForEach)
- C#使用yield关键字让自定义集合实现foreach遍历的方法
- ECMAScript5新增Array方法forEach的实现
- ECMAScript5新增Array方法forEach的实现
- C#方法返回IEnumerable实现用foreach遍历
- Java方法传参和可变参数的个别说明,以及foreach的语法和编译后的实现
- C# 列表类Find()方法的Predicate match参数 和 ForEach()方法的Action action参数实现
- 能用foreach遍历访问的对象需要实现____接口或声明____方法的类型
- 自定义类的索引器实现及foreach方法的实现
- ECMA5数组的新增方法有哪些及forEach()模仿实现