简介
- 用foreach需要提供一个可枚举类型的实例
- 要让一个类型变为可枚举的(可枚举类型),需要该类型实现IEnumerable接口,并实现该接口的GetEnumerator方法,GetEnumerator方法返回枚举器实例
- 可以用yield块来让编译器生成嵌套在可枚举型内部的枚举器类(这种结构被称为迭代器),也可以自定义枚举器类(需要实现IEnumerator接口)
- 枚举器通过构造函数传入的参数初始化(复制)枚举项,通过MoveNext取得下一个枚举项,通过Current属性返回当前枚举项,所以说枚举器是只读的,
创建枚举器的方式
创建枚举器类,并实现IEnumerable接口
手动创建一个类型并实现IEnumerable接口和接口的Current,MoveNext,Reset方法
/// <summary>
/// 可枚举类型
/// </summary>
/// <typeparam name="T"></typeparam>
public class MyEnumerableClass<T> : IEnumerable<T>
{
private T[] _values;
public MyEnumerableClass(T[] values)
{
_values = values;
}
IEnumerator IEnumerable.GetEnumerator()
{
return new MyEnumerator<T>(_values);
}
IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
return new MyEnumerator<T>(_values);
}
}
/// <summary>
/// 自定义枚举器
/// </summary>
/// <typeparam name="T"></typeparam>
public class MyEnumerator<T> : IEnumerator<T>
{
private T[] _values;
private int _position;
public MyEnumerator(T[] values)
{
_values = new T[values.Length];
for (int i = 0; i < _values.Length; i++)
{
_values[i] = values[i];
}
_position = -1;
}
object IEnumerator.Current
{
get
{
if (0 <= _position && _position < _values.Length) return _values[_position];
else throw new InvalidOperationException();
}
}
T IEnumerator<T>.Current
{
get
{
if (0 <= _position && _position < _values.Length) return _values[_position];
else throw new InvalidOperationException();
}
}
bool IEnumerator.MoveNext()
{
bool isValid = _position < _values.Length - 1;
if (isValid) { _position++; }
return isValid;
}
void IEnumerator.Reset()
{
_position = -1;
}
void IDisposable.Dispose()
{
}
}
测试
var myClass = new MyEnumerableClass<int>(new int[] { 3, 4, 5 });
foreach (var item in myClass)
{
Debug.Log($"item = {item}");
}
用迭代器创建枚举器
编译器从迭代器块得到有关如何枚举项的描述后,使用这些信息来构建包含所有需要的方法和属性实现的枚举器类(这个类作为嵌套类被包括在迭代器声明的类中) GetEnumerator()
的返回值是生成的嵌套的枚举器类的实例
public class MyEnumeratorClass
{
public IEnumerator<string> GetEnumerator()
{
yield return "test1";
}
}
测试
MyEnumeratorClass myClass = new MyEnumeratorClass();
foreach (var item in myClass)
{
Debug.Log($"item = {item}");
}
用迭代器创建可枚举类型
public class MyEnumerableEnumeratorClass
{
public IEnumerator<string> GetEnumerator()
{
// 获取可枚举类型
IEnumerable<string> myEnumerable = GetEnumerableObject();
// 从可枚举类型实例中获得枚举器
return myEnumerable.GetEnumerator();
}
/// <summary>
/// 返回一个既实现了IEnumerator,又实现了IEnumerable的嵌套类的实例,它即是可枚举类型(可以被foreach,注意这段代码中没有任何class实现了IEnumerable),也是枚举器(为可枚举类型提供如何枚举的描述)
/// </summary>
/// <returns></returns>
public IEnumerable<string> GetEnumerableObject()
{
yield return "test1";
}
}
测试
MyEnumerableEnumeratorClass myClass = new MyEnumerableEnumeratorClass();
foreach (var item in myClass)
{
Debug.Log($"item = {item}");
}
foreach (var item in myClass.GetEnumerableObject())
{
Debug.Log($"item = {item}");
}