csharp 缓存枚举器,确保源枚举器只迭代一次
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了csharp 缓存枚举器,确保源枚举器只迭代一次相关的知识,希望对你有一定的参考价值。
//latest version is here: https://gist.github.com/b1059488d17c52da5a732a100ba6e09f.git
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
namespace CachingEnumeratorUtils
{
/// <summary>
/// Enumerable doing lazy caching of enumerator, to avoid generating items more than one time
/// </summary>
/// <typeparam name="T"></typeparam>
public class CachingEnumerator<T> : IEnumerable<T>, IDisposable
{
public CachingEnumerator(IEnumerable<T> source)
{
this.sourceEnumerator = source.GetEnumerator();
}
public CachingEnumerator(IEnumerator<T> source)
{
this.sourceEnumerator = source;
}
/// <summary>
/// Items that were already generated by source enumerator
/// </summary>
public IEnumerable<T> CachedItems { get { return cachedItems; } }
/// <summary>
/// Amount of items that were cached already
/// </summary>
public int CachedItemsCount { get { return cachedItems.Count; } }
/// <summary>
/// Indicates if all items cached and source is complete
/// </summary>
public bool IsCachedAll { get { return sourceEnumeratorFinished; } }
//public IEnumerable<T> Source { get; private set; }
IEnumerator<T> sourceEnumerator;
LinkedList<T> cachedItems = new LinkedList<T>();
bool sourceEnumeratorFinished = false;
bool sourceEnumeratorStarted = false;
LinkedListNode<T> CacheNext()
{
if (sourceEnumeratorFinished) return null;
sourceEnumeratorStarted = true;
sourceEnumeratorFinished = !sourceEnumerator.MoveNext();
if (sourceEnumeratorFinished)
{
DisposeSource();
return null;
}
var node = cachedItems.AddLast(sourceEnumerator.Current);
return node;
}
IEnumerable<T> GetItems()
{
if (!sourceEnumeratorStarted) CacheNext();
var current = cachedItems.First;
while (current != null)
{
yield return current.Value;
current = current.Next ?? CacheNext();
}
}
public IEnumerator<T> GetEnumerator()
{
return GetItems().GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
bool sourceDisposed = false;
void DisposeSource()
{
if (sourceDisposed) return;
sourceEnumerator.Dispose();
sourceDisposed = true;
}
public void Dispose()
{
}
}
/// <summary>
/// Extensions that help to use CachingEnumerator
/// </summary>
public static class CachingEnumeratorExtensions
{
/// <summary>
/// Make sure enumerator will be only iterated once and items generated will be cached
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source"></param>
/// <returns></returns>
public static CachingEnumerator<T> AsCaching<T>(this IEnumerable<T> source)
{
return new CachingEnumerator<T>(source);
}
/// <summary>
/// Make sure enumerator will be only iterated once and items generated will be cached
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source"></param>
/// <returns></returns>
public static CachingEnumerator<T> AsCaching<T>(this IEnumerator<T> source)
{
return new CachingEnumerator<T>(source);
}
}
}
以上是关于csharp 缓存枚举器,确保源枚举器只迭代一次的主要内容,如果未能解决你的问题,请参考以下文章
csharp Python中内置的枚举函数可以把一个列表变成索引 - 元素对,这样就可以在对循环中同时迭代索引和元素本身: