C# 迭代器

IEnumerator

实现 IEnumerator 接口的类才是真正的迭代器,它定义了各项元素被循环访问的逻辑。

// 实现 IEnumerator
public class WeekEnumerator : IEnumerator
{
    string[] week = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
    int position = -1;

    public object Current => week[position];

    public bool MoveNext()
    {
        position++;
        return position < week.Length;
    }

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

// 循环迭代器
var week = new WeekEnumerator ();
while (week .MoveNext())
{
	Debug.Log(week.Current);
}
yield return

yield 是一种语法糖,会自动实现 IEnumerator 接口的 Current、MoveNext 等方法。即完成 MonthEnumerator 所做的事。所以,语句中使用了 yield 关键字的方法、运算符或 get 访问器也是迭代器。

使用多个 yield 语句,可以代替手动实现 IEnumerator 的繁琐操作。

// 定义迭代器方法
IEnumerator GetWeek()
{
	// 多个 yield 语句合起来生成了一个实现 IEnumerator 接口的类(相当于 WeekEnumerator )
	// yield return 的返回类型是 IEnumerator
	yield return "Mon";
	yield return "Tue";
	yield return "Wed";
	yield return "Thu";
	yield return "Fri";
	yield return "Sat";
	yield return "Sun";
}

// 循环这个迭代器方法
var week = GetWeek();
while (week.MoveNext())
{
	Debug.Log(week.Current);
}
IEnumerable

IEnumerable 接口实际上就是简化了循环访问,包装了 IEnumerator 以便通过 foreach 进行循环

// IEnumerable 接口只有一个获取 IEnumerator 的方法
public interface IEnumerable
{
	IEnumerator GetEnumerator();
}

// 使用 foreach 循环 List,它是实现了 IEnumerable 接口的类型
var array = new List<int> { 100, 101, 102 };
foreach (var item in array)
{
	Debug.Log(item);
}

// 这是编译器内部转换的 foreach 代码
var enumerator = array.GetEnumerator();
while (enumerator.MoveNext())
{
	Debug.Log(enumerator.Current);
}

即,IEnumerator 类在使用 IEnumerable 接口包装后,可使用 foreach 循环,否则需使用 MoveNext 手动完成。C# 中自带集合,一般都实现自 IEnumerable 接口,方便可用 foreach 进行迭代。

使用 IEnumerable 与 IEnumerator 自定义集合
// 实现 IEnumerable 接口
public class Week : IEnumerable
{
	// 只为取得 IEnumerator
    public IEnumerator GetEnumerator()
    {
        return new WeekEnumerator();
    }
}

// 实现 IEnumerator 接口
public class WeekEnumerator : IEnumerator
{
	// 和第一个示例中一样
    ...
}

由于 yield 帮助生成 IEnumerator 类型,所以可以使用 yield 来简化自定义集合的定义

// 只需要实现 IEnumerable 接口,通过 yield 语法糖生成 IEnumerator
public class Week : IEnumerable
{
    string[] days = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };

    public IEnumerator GetEnumerator()
    {
        for (int i = 0; i < days.Length; i++)
        {
            yield return days[i];
        }
    }
}

你可能感兴趣的:(Unity)