C#迭代器
文档
C# Iterators
关键内容
- 普通接口
public interface IEnumerable
{IEnumerator GetEnumerator();
}public interface IEnumerator
{object Current { get; }bool MoveNext();void Reset();
}
- 泛型接口
public interface IEnumerable<out T> : IEnumerable
{IEnumerator<T> GetEnumerator();
}
public interface IEnumerator<out T> : IEnumerator, IDisposable
{T Current { get; }
}
- yield return
使用yield return可简化迭代器的生成,不需要自己手动创建类进行实现。
注意:使用yield return生成的迭代器,无法使用Reset。
如需Reset,可自定义迭代器类,进行实现。
示例
TransformForeach1实现泛型接口IEnumerable,自己实现迭代器
TransformForeach2实现泛型接口IEnumerable,使用yield return实现迭代器
对比得知:yield return 可方便的简化迭代器生成
注意:如果实现泛型版本接口,yield return 返回类型要和泛型指定的类型一致
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Test04 : MonoBehaviour
{TransformForeach1 foreachTransform1;IEnumerator<Transform> ator1;TransformForeach2 foreachTransform2;IEnumerator<Transform> ator2;void Start(){int childCount = 5;for (int i = 0; i < childCount; i++){var obj = new GameObject(i.ToString());obj.transform.SetParent(transform);}foreachTransform1 = new TransformForeach1(transform);ator1 = foreachTransform1.GetEnumerator();foreachTransform2 = new TransformForeach2(transform);ator2 = foreachTransform2.GetEnumerator();}private void Update(){if (Input.GetKeyDown(KeyCode.Space)){//使用类实现泛型迭代器接口 可使用Reset方法Debug.Log("1...");while (ator1.MoveNext()){Debug.Log(ator1.Current);}ator1.Reset();foreach (var item in foreachTransform1){Debug.Log(item);}Debug.Log("2...");//使用yield return实现泛型迭代器接口,无法使用Reset方法try{while (ator2.MoveNext()){Debug.Log(ator2.Current);}ator2.Reset();}catch (System.Exception e){Debug.LogException(e);} foreach (var item in foreachTransform2){Debug.Log(item);}}}private class TransformForeach1 : IEnumerable<Transform>{Transform transform;public TransformForeach1(Transform transform){this.transform = transform;}public IEnumerator<Transform> GetEnumerator(){return new Enumerator(transform);}IEnumerator IEnumerable.GetEnumerator(){return GetEnumerator();}private class Enumerator : IEnumerator<Transform>{int index = -1;Transform transform;public Enumerator(Transform transform){this.transform = transform;}public Transform Current => transform.GetChild(index);object IEnumerator.Current => Current;public void Dispose(){}public bool MoveNext(){var childCount = transform.childCount;return ++index < childCount;}public void Reset(){index = -1;}}}private class TransformForeach2 : IEnumerable<Transform>{Transform transform;public TransformForeach2(Transform transform){this.transform = transform;}public IEnumerator<Transform> GetEnumerator(){var length = transform.childCount;for (int i = 0; i < length; i++)yield return transform.GetChild(i);}IEnumerator IEnumerable.GetEnumerator(){return GetEnumerator();}}
}