授人以渔(一)——从C#到Unity的协程(上篇)

本文深入解析了C#协程中的枚举器和迭代器概念,介绍了它们的工作原理、用途,并通过实例展示了如何使用和它们之间的差异。重点讲解了foreach遍历背后的IEnumerable接口和IEnumerator接口,以及迭代器带来的便利和性能优势。

C#协程的深入挖掘:

要弄懂协程,首先要明白枚举器和迭代器的区别:
  • 枚举器:
  • ①foreach的本质,一个实现了IEnumerable接口的类的实例可以用foreach遍历。
  • Why——因为IEnumerable接口中定义了一个方法,这个方法返回一个IEnumerator类型对象。
  • ★(Enumerator)枚举器可以依次返回请求的数组中的元素,枚举器知道项的次序并且跟踪它在序列中的位置。依次返回请求的当前项。但枚举器只允许访问集合中的数据,无法修改集合中的数据。
  • ②IEnumrator接口
  • IEnumrator接口包含了3个函数成员:Current、MoveNext以及Reset;
  • .Current是返回序列中当前位置项的属性。(注意:Current它是只读属性,它返回Object类型的引用,所以可以返回任意类型)
  • .MoveNext是把枚举器位置前进到集合中下一项的方法。它返回布尔值,指示新的位置是否是有效位置。
  • 枚举器的原始位置在序列中的第一项之前,因此MoveNext必须在第一次使用Current之前调用。
  • .Reset是把位置重置为原始状态的方法。
  • ③IEnumerable接口
  • 数组是可枚举类型,是因为实现了IEnumerable接口的类,所以可枚举类都是因为实现了IEnumerable接口的类。
  • IEnumerable接口只有一个成员——GetEnumerator()方法,它返回对象的枚举器。
using System; using System.Collections; // 创建枚举器 class ColorEnumerator : IEnumerator { string[] _colors; // 用于存储内部的 color 数组 int _position = -1; // 用于表示枚举器位置 // 构造函数 public ColorEnumerator(string[] theColors) { _colors = new string[theColors.Length]; for (int i = 0; i < theColors.Length; i++) { _colors[i] = theColors[i]; } } // 实现 Current public object Current { get { if (_position == -1) { throw new InvalidOperationException(); } if (_position >= _colors.Length) { throw new InvalidOperationException(); } return _colors[_position]; } } // 实现MoveNext public bool MoveNext() { if (_position < _colors.Length - 1) { _position++; return true; } else { return false; } } // 实现 Reset public void Reset() { _position = -1; } } // 可枚举类,实现 IEnumrable 接口,提供 GetEnumerator class ColorBase : IEnumerable { string[] Colors = { "violet", "blue", "cyan", "green" }; public IEnumerator GetEnumerator() { return new ColorEnumerator(Colors); } } class Program { static void Main() { ColorBase cb = new ColorBase(); foreach (string color in cb) { Console.WriteLine(color); } } }
  • 拓展:泛型枚举接口IEnumerable<T>和IEnumerator<T>,我们更应该使用泛型的枚举接口。
  • Why——因为IEnumerable的GetEnumerator方法返回IEnumerator枚举类的实例,而IEnumerator枚举类里实现了Current属性(一个object类型),所以在使用时存在拆箱操作(损耗性能),而泛型的IEnumerator<T>枚举类直接返回实际类型的对象。并且只要集合不变,枚举器就有效,但集合一旦发生改变,则枚举器会失效(和C++的迭代器一样)
  • 迭代器:
  • 迭代器是C#2.0引入的,使用yield关键字让编译器代替我们完成了枚举类型和枚举器的创建。
//迭代器返回一个泛型枚举器(并没有实现IEnumerator接口的Reset方法) public IEnumerator<string> GetEnumeratorTwo(){ yield return "violet"; yield return "blue"; yield return "cyan"; yield return "green"; } class MyClass{//可枚举类型 public IEnumerator<string> GetEnumerator(){ return GetEnumeratorTwo(); } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值