枚举器和迭代器

本文详细介绍了C#中如何创建可枚举类型和自定义枚举器,包括实现IEnumerable接口、使用yield关键字创建迭代器以及通过嵌套类生成枚举器。同时,展示了通过迭代器创建枚举器和可枚举类型的不同方法,并提供了相关测试代码进行示例。
摘要由CSDN通过智能技术生成

简介

  • 用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}");
}

产生多个可枚举类型

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值