自定义迭代类
》》》using System.Collections;
using System.Collections;
using System.Runtime.CompilerServices;
namespace ConsoleApp1
{
// 可迭代对象 标记此类可迭代 继承IEnumerable 类是可以迭代
public class SpecificEnumerable : IEnumerable
{
private readonly object[] _dataSource;
public SpecificEnumerable(object[] values)
{
_dataSource = values;
}
public IEnumerator GetEnumerator()
{
return new SpecificEnumerator(_dataSource);
}
// 迭代器 工作引擎
internal class SpecificEnumerator : IEnumerator
{
private int _position; // 指针
private readonly object[] _data; // 数据源
public SpecificEnumerator(object[] data)
{
_position = -1;
_data = data;
}
public bool MoveNext()
{
if (_position != _data.Length)
{
_position++;
}
return _position >= 0 && _position < _data.Length;
}
public void Reset()
{
_position = -1;
}
public object Current
{
get
{
if (_position == -1 || _position == _data.Length)
{
throw new IndexOutOfRangeException();
}
return _data[_position];
}
}
}
}
class Program
{
static void Main(string[] args)
{
#region 自定义可枚举类
var myEnumerable = new SpecificEnumerable(new object[]
{
"A", "B", "C", "D"
});
foreach (var item in myEnumerable)
{
Console.WriteLine(item);
}
Console.WriteLine("=========================>");
var myEnumerator = myEnumerable.GetEnumerator();
while (myEnumerator.MoveNext())
{
Console.WriteLine(myEnumerator.Current);
}
#endregion
}
}
}
用yield return
using System.Collections;
using System.Runtime.CompilerServices;
namespace ConsoleApp1
{
public class SpecificYieldEnumerable : IEnumerable
{
private readonly Random _random = new();
private readonly int _capacity;
public SpecificYieldEnumerable(int count)
{
_capacity = count;
}
public IEnumerator GetEnumerator()
{
for (var i = 0; i < _capacity; i++)
{
yield return _random.Next(100);
}
}
}
class Program
{
static void Main(string[] args)
{
var myEnumerable = new SpecificYieldEnumerable(10);
foreach (var item in myEnumerable)
{
Console.WriteLine(item);
}
Console.WriteLine("=================>");
var myEnumerator = myEnumerable.GetEnumerator();
while (myEnumerator.MoveNext())
{
Console.WriteLine(myEnumerator.Current);
}
}
}
}
针对整个集合中的每一个元素执行操作,那么程序的效率会很低。
把通用的IEnumerable或针对某种类型的IEnumerable设计成方法的输入及输出参数是一种比较少见的思路,因此,很多开发者都不会这样去做,但是这种思路确实能带来很多好处。
迭代器方法会等调用方真正用到某个元素时才去执行相应的代码,与传统的命令式方法相比,这种延迟执行(deferred execution,机制可以降低算法所需的存储空间,并使算法的各个部分之间能够更为灵活地拼接起来
迭代器方法真正强大之处在于它可以把多个步骤拼接成一整套流程。
如果能把复杂的算法拆解成多个步骤,并把每个步骤都表示成这种小型的迭代器方法,
那么就可以将这些方法拼成一条管道,使得程序只需把源序列处理一遍即可对其中的元素执行许多种小的变换。
就好比 循环计算 ,每次都计算结果,在把结果跟下一个数进行计算。
int result=0;
for(int i=1;i<100;i++)
{
result +=i;
}
迭代器 是 1+2+3.。。。。99 一起计算的。 效率比较高
// 为了演示迭代器方法的好处,笔者先举一个简单的例子,然后用迭代器方法改写。
public static void Unique(IEnumerable<int> nums)
{
var uniqueVals = new HashSet<int>();
foreach(var num in nums)
{
if(!uniqueVals.Contains(num))
{
uniqueVals.Add(num);
Console.WriteLine(num);
}
}
}
// 为此,可以考虑改用迭代器方法来实现:
public static IEnumerable<int> UniqueV2(IEnumerable<int> nums)
{
var uniqueVals = new HashSet<int>();
foreach (var num in nums)
{
if (!uniqueVals.Contains(num))
{
uniqueVals.Add(num);
yield return num;
}
}
}