将枚举器(不可枚举)类型映射到另一种类型的枚举器

Map enumerator (not enumerable) type to an enumerator of another type

如何将 IEnumerator<KeyValuePair<TKey, TValue>> 转换为包含键值对中的键的 IEnumerator<TKey>

更一般地说,如果存在从 TSourceTTarget 的转换,我如何将 IEnumerator<TSource> 转换为 IEnumerator<TTarget>

请注意,此问题并非寻求有关如何枚举枚举数(使用 MoveNextCurrent)或如何将枚举数转换为可枚举数的信息(参见 this discussion), or how to transform an enumerable to an enumerator (just call GetEnumerator() on the IEnumerable<T>), or how to map an enumerable to another type (see this discussion ).

我已经提供了我自己提出的答案作为答案,但当然我很高兴听到其他方法。

我比较喜欢的做法如下。 (也可以将其定义为 struct 而不是 class,例如减少堆分配。)

public class TransformEnumerator<TSource, TTarget> : IEnumerator<TTarget>
{
    IEnumerator<TSource> SourceEnumerator;
    Func<TSource, TTarget> TransformFunc;

    public TransformEnumerator(IEnumerator<TSource> sourceEnumerator, Func<TSource, TTarget> transformFunc)
    {
        SourceEnumerator = sourceEnumerator;
        TransformFunc = transformFunc;
    }

    public TTarget Current => TransformFunc(SourceEnumerator.Current);

    object IEnumerator.Current => TransformFunc(SourceEnumerator.Current);

    public void Dispose()
    {
        SourceEnumerator.Dispose();
    }

    public bool MoveNext()
    {
        return SourceEnumerator.MoveNext();
    }

    public void Reset()
    {
        SourceEnumerator.Reset();
    }
}

这是一种方法,使用 static class:

public static class TransformEnumerator2<TSource, TTarget>
{
    public static IEnumerator<TTarget> GetEnumerator(IEnumerator<TSource> source, Func<TSource, TTarget> transformFunc)
    {
        return (IEnumerator<TTarget>)GetEnumerable(source, transformFunc);
    }

    private static IEnumerable<TTarget> GetEnumerable(IEnumerator<TSource> source, Func<TSource, TTarget> transformFunc)
    {
        while (source.MoveNext())
            yield return transformFunc(source.Current);
    }
}

请注意,GetEnumerable 方法是私有的。在一个publicAPI中,客户端希望一个enumerable可以多次使用,但是这里的enumerable只能使用一次。但是,由于 Reset 的行为是未定义的,因此 Enumerator 预计只会被使用一次,所以这就实现了它的目标。