发文章
发文工具
撰写
网文摘手
文档
视频
思维导图
随笔
相册
原创同步助手
其他工具
图片转文字
文件清理
AI助手
留言交流
1、C#中的迭代器的作用 http://zhidao.baidu.com/question/110561432.html
2、详解C#迭代器 http://www.cnblogs.com/yangecnu/archive/2012/03/17/2402432.html
3、msdn 迭代器 http://msdn.microsoft.com/zh-cn/library/dscyy5s0(VS.80).aspx
4、C# IEnumerable和IEnumerator的区别 http://www.cnblogs.com/shaosks/archive/2011/09/27/2193270.html
一、迭代器的作用
看了好几篇文章,也翻了翻《C#4.0图解教程》,还是觉得如下这段写的不错
<
SPAN
style
=
"FONT-SIZE: 15px"
>你需要理解什么是数组Array,什么是集合IConnection,什么是IList开始.
举个简单例子:
数组如 string ar=new string[]{"a","b","c"}
这是一个简单字符串数组。
假设我需要提取数组中的每一个元素,我该怎么办呢?
所以那些天才们就想出一种方案,用C#语法表达是:
forech(string item in ar)
{
MessageBox.Show(item);
}
然后你可以把forech(string item in ar)这种语法理解为迭代器.
"COLOR: #339966"
>专业解释:</
>
STRONG
>1.迭代器是可以返回相同类型值的有序序列的一段代码;
2.迭代器可用作方法、运算符或get访问器的代码体;
3.迭代器代码使用yield return语句依次返回每个元素,yield break将终止迭代;
4.可以在类中实现多个迭代器,每个迭代器都必须像任何类成员一样有惟一的名称,并且可以在foreach语句中被客户端代码调用;
5.迭代器的返回类型必须为IEnumerable和IEnumerator中的任意一种;
6.迭代器是产生值的有序序列的一个语句块,不同于有一个 或多个yield语句存在的常规语句块;
7.迭代器不是一种成员,它只是实现函数成员的方式,理解这一点是很重要的,一个通过迭代器实现的成员,可以被其他可能或不可能通过迭代器实现的成员覆盖和重载;
8.迭代器块在C#语法中不是独特的元素,它们在几个方面受到限制,并且主要作用在函数成员声明的语义上,它们在语法上只是语句块而已;
</
></
迭代器模式是设计模式中行为模式(behavioral pattern)的一个例子,他是一种简化对象间通讯的模式,也是一种非常容易理解和使用的模式。简单来说,迭代器模式使得你能够获取到序列中的所有元素而不用关心是其类型是array,list,linked list或者是其他什么序列结构。这一点使得能够非常高效的构建数据处理通道(data pipeline)--即数据能够进入处理通道,进行一系列的变换,或者过滤,然后得到结果。事实上,这正是LINQ的核心模式。
在C#1中已经内建了对迭代器的支持,那就是foreach语句。使得能够进行比for循环语句更直接和简单的对集合的迭代,编译器会将foreach编译来调用GetEnumerator和MoveNext方法以及Current属性,如果对象实现了IDisposable接口,在迭代完成之后会释放迭代器。但是在C#1中,实现一个迭代器是相对来说有点繁琐的操作。C#2使得这一工作变得大为简单,节省了实现迭代器的不少工作。
二、简单代码实现:
《深入理解C# 第二版》中关于C#1.0 实现迭代其的代码如下:
(1)声明IEnumerable接口
1 public class IterationSample:IEnumerable 2 { 3 public object[] values; 4 public int startingPoint; 5 public IterationSample(object[] values,int startingPoint) 6 { 7 this.values = values; 8 this.startingPoint = startingPoint; 9 } 10 public IEnumerator GetEnumerator() 11 { 12 return new IterationSampleIterator(this) ; 13 } 14 }
(2)实现IEnumerator接口
1 class IterationSampleIterator:IEnumerator 2 { 3 IterationSample parent; 4 int position; 5 internal IterationSampleIterator(IterationSample parent) 6 { 7 this.parent = parent; 8 position = -1; 9 } 10 public bool MoveNext() 11 { 12 if(position!=parent.values.Length) 13 { 14 position++; 15 } 16 return position < parent.values.Length; 17 } 18 public object Current 19 { 20 get 21 { 22 if (position == -1 || position == parent.values.Length) 23 { 24 throw new InvalidOperationException(); 25 } 26 int index = position + parent.startingPoint; 27 index = index % parent.values.Length; 28 return parent.values[index]; 29 } 30 } 31 public void Reset() 32 { 33 position = -1; 34 } 35 }
(3)Main()方法中的代码实现
1 static void Main(string[] args) 2 { 3 bool isGo = true; 4 while (isGo) 5 { 6 Console.WriteLine("输入一个起始位置(1-5之间)"); 7 int startPoint = int.Parse(Console.ReadLine()); 8 object [] values = { "a", "b", "c", "d", "e" }; 9 IterationSample it = new IterationSample(values, startPoint-1); 10 foreach (object item in it) 11 { 12 Console.WriteLine(item); 13 } 14 Console.WriteLine("是否继续(Y/N)"); 15 switch (Console.ReadLine()) 16 { 17 case "Y": 18 isGo = true; 19 break; 20 case "y": 21 isGo = true; 22 break; 23 case "N": 24 isGo = false; 25 break; 26 case "n": 27 isGo = false; 28 break; 29 } 30 } 31 Console.ReadKey(); 32 } 33 }
我们发现这样手写来实现迭代器的功能代码量确实有写太大了,那么在C#2.0中就采用yield语句简单迭代
1 class IterationSample:IEnumerable 2 { 3 object[] values; 4 int startingPoint; 5 public IterationSample(object[]values,int startingPoint) 6 { 7 this.values = values; 8 this.startingPoint = startingPoint; 9 } 10 public IEnumerator GetEnumerator() 11 { 12 for (int index = 0; index < values.Length;index++ ) 13 { 14 yield return values[(index+startingPoint)%values.Length]; 15 } 16 } 17 } 18 19 static void Main(string[] args) 20 { 21 object[] values = { "a","b","c","d","e"}; 22 int startPoint = 2; 23 IterationSample it = new IterationSample(values,startPoint); 24 foreach (object item in it) 25 { 26 Console.WriteLine(item); 27 } 28 Console.ReadKey(); 29 }
三、对以上的总结:以上是不使用接口的枚举数
缺点:
1、Current返回的对象是object类型,对于值类型而言,在由Current返回之前必须装箱成object,在从Current获取之后,又必须再一次拆箱,如果需要操作大量的数据,会打来严重的性能问题、
2、类型不安全。值被作为对象来枚举,所以可以是任何类型,这就消除了编译时的类型检测。
四、泛型接口 IEnumerator<T> IEnumerable<T>
IEnumerator<T>接口使用泛型来返回实际的类型,而不是object类型的引用
1 class ColorEnumerator : IEnumerator<string> 2 { 3 string[] Colors; 4 int Position = -1; 5 public ColorEnumerator(string [] colors) 6 { 7 Colors=new string[colors.Length]; 8 for (int i = 0; i < colors.Length;i++ ) 9 { 10 Colors[i] = colors[i]; 11 Console.WriteLine(Colors[i]); 12 } 13 } 14 public string Current 15 { 16 get 17 { 18 return Colors[Position]; 19 } 20 } 21 object IEnumerator.Current 22 { 23 get 24 { 25 return Colors[Position]; 26 } 27 } 28 public bool MoveNext() 29 { 30 if (Position < Colors.Length - 1) 31 { 32 Position++; 33 return true; 34 } 35 else 36 { 37 return false; 38 } 39 } 40 public void Reset() 41 { 42 Position = -1; 43 } 44 public void Dispose() 45 { 46 this.Dispose(); 47 } 48 }
IEnumerable
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Collections; 6 //using System.Collections.Generic; 7 8 namespace IEnumerator_T 9 { 10 class Program 11 { 12 static void Main(string[] args) 13 { 14 //string[] colors = { "Red","Green","Blue"}; 15 //ColorEnumerator col = new ColorEnumerator(colors); 16 //Console.ReadKey(); 17 MyColors my = new MyColors(); 18 foreach (string item in my) 19 { 20 Console.WriteLine(item); 21 } 22 Console.ReadKey(); 23 } 24 } 25 26 class ColorEnumerator : IEnumerator<string> 27 { 28 string[] Colors; 29 int Position = -1; 30 public ColorEnumerator(string [] colors) 31 { 32 Colors=new string[colors.Length]; 33 for (int i = 0; i < colors.Length;i++ ) 34 { 35 Colors[i] = colors[i]; 36 // Console.WriteLine(Colors[i]); 37 } 38 } 39 public string Current 40 { 41 get 42 { 43 return Colors[Position]; 44 } 45 } 46 object IEnumerator.Current 47 { 48 get 49 { 50 return Colors[Position]; 51 } 52 } 53 public bool MoveNext() 54 { 55 if (Position < Colors.Length - 1) 56 { 57 Position++; 58 return true; 59 } 60 else 61 { 62 return false; 63 } 64 } 65 public void Reset() 66 { 67 Position = -1; 68 } 69 public void Dispose() 70 { 71 // this.Dispose(); 72 } 73 } 74 class MyColors:IEnumerable<string> 75 { 76 string[] Colors = { "Red","Yellow","Blue"}; 77 public IEnumerator<string> GetEnumerator() 78 { 79 return new ColorEnumerator(Colors); 80 } 81 IEnumerator IEnumerable.GetEnumerator() 82 { 83 return new ColorEnumerator(Colors); 84 } 85 } 86 }
五、由于上面的种种不便,迭代器开始闪亮登场了
1、迭代器可自动帮助生成可枚举类型和枚举数
使用迭代器来创建枚举数
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace 使用迭代器创建可枚举数 7 { 8 class Program 9 { 10 static void Main(string[] args) 11 { 12 MyClaa mc = new MyClaa(); 13 foreach (string item in mc) 14 { 15 Console.WriteLine(item); 16 } 17 Console.ReadKey(); 18 } 19 } 20 class MyClaa 21 { 22 public IEnumerator<string> GetEnumerator() 23 { 24 return BlackAndWhite(); 25 } 26 public IEnumerator<string> BlackAndWhite() 27 { 28 yield return "blcak"; 29 yield return "white"; 30 yield return "gray"; 31 } 32 } 33 }
BlackAndWhite迭代器方法返回IEnumerator<string>,MyClaa类通过返回由BlackAndWhite返回的对象来实现GetEnumerator方法
使用迭代器来创建可枚举类型
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace 使用迭代器来创建可枚举类型 7 { 8 class Program 9 { 10 static void Main(string[] args) 11 { 12 MyClass my = new MyClass(); 13 foreach (string item in my) 14 { 15 Console.WriteLine(item); 16 } 17 //foreach (string item in my.BlackAndWhite) 18 //{ 19 20 //} 21 Console.ReadKey(); 22 } 23 } 24 class MyClass 25 { 26 public IEnumerator<string> GetEnumerator() 27 { 28 //获取可枚举对象 29 IEnumerable<string> myEnumerable = BlackAndWhite(); 30 //获取可枚举数 31 return myEnumerable.GetEnumerator(); 32 } 33 public IEnumerable<string> BlackAndWhite() 34 { 35 yield return "black"; 36 yield return "gray"; 37 yield return "green"; 38 } 39 } 40 }
六、总结一下:
(1)简单来说IEnumerable是声明式接口 public interface IEnumerable
IEnumerator GetEnumerator();
(2)IEnumerator是实现式接口
public interface IEnumerator
object Current(get;);
bool MoveNext();
void Reset();
(3)Collection要支持foreach进行遍历就必须实现IEnumerable,并以某种方式返回迭代器对象IEnumerator 。
来自: 昵称10504424 > 《工作》
0条评论
发表
请遵守用户 评论公约
什么是迭代器,创建并使用迭代器.为整数列表创建迭代器.为泛型列表创建迭代器 - さびしい....
什么是迭代器,创建并使用迭代器.为整数列表创建迭代器.为泛型列表创建迭代器 - さびしい....什么是迭代器,创建并使用迭代器.为整数列表创建迭代器.为泛型列表创建迭代器 收藏 迭代器导读什么是迭代器创...
【转】【C#】迭代器IEnumerable和IEnumerator
这条语句告诉编译器这不是一个普通的方法,而是一个需要执行的迭代块(yield block),他返回一个IEnumerator对象,你能够使用迭代块来...
一文说通C#中的异步迭代器
一文说通C#中的异步迭代器。await foreach (var item in Sources){ Console.如果有CancellationToken通过WithCancellation传过来,迭代器会在正确的时间被取消 - 包括异步获取数据期间(例子中的Task.D...
C#的枚举数(Enumerator)和可枚举类型(Enumerable)
class MyEnumerable : IEnumerable //定义一个可枚举类型的类 { string[] MyColor = new string[] { "yellow", "red", "black", "white"...
C#迭代
2.迭代器是C# 2.0中的新功能,它是方法、get访问器或运算符,它使开发人员能够在类或结构中支持foreach迭代,而不必实现整个IEnumerable接口。可以在类中实现多个迭代器,每个迭代器都必须像任何类成员...
Linq之前的C#知识
} static void Print(List<int> arr,moreOrlessDelgate dl) { foreach (var item in arr) { if (...
C#中的foreach和yield
Linq之延迟加载特性
Linq之延迟加载特性目录。1 static void Main(string[] args) 2 { 3 List<Person> persons = new List<Person>() { 4 new Person(){ ID=1,Name="wolfy1", Age=1}, 5 new Person...
C# IEnumerable和IEnumerator的区别,如何实现
IEnumerable接口和IEnumerator接口是.NET中非常重要的接口,二者有何区别?public interface IEnumerable { IEnumerator GetEnumerator();3.一个collection要支持Foreach进行遍...
微信扫码,在手机上查看选中内容