[英]How to make my InfiniteLoopingList class implement IEnumerable?
我正在制作一個原型應用程序,為此,我設計了一個行為類似於無限循環列表的類。 也就是說,如果我的內部列表包含100個值,則當我要求第101個值時,我得到第一個,第102個產生第二個,依此類推,重復進行。
所以我想寫下面的代碼:
var slice = loopingListInstance.Skip(123).Take(5);
據我所知,為此,我需要實現合適的IEnumerable。
這是我當前的代碼:
public class InfiniteLoopingList : IEnumerable<double>
{
double[] _values = File.ReadLines(@"c:\file.txt")
.Select(s => double.Parse(s, CultureInfo.InvariantCulture))
.ToArray();
int _size;
public InfiniteLoopingList()
{
_size = _values.Length;
}
public double this[int i]
{
get { return _values[i % _size]; }
set { _values[i % _size] = value; }
}
public IEnumerator<double> GetEnumerator()
{
return this.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
// ???? now what ?? :(
}
}
由於實現了indexer屬性,因此可以通過以下最簡單的方法進行操作:
public IEnumerator<double> GetEnumerator()
{
int i = 0;
while (true)
yield return this[i++];
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
編輯
請注意,這並不是真正的無限循環。 該方法僅在i = int.MaxValue
之前i = int.MaxValue
。 感謝@oleksii。
您不需要為此上課...
擴展方法可以解決這個問題:
public static class InfEx
{
public static IEnumerable<T> LoopForever<T>(this IEnumerable<T> src)
{
var data = new List<T>();
foreach(var item in src)
{
data.Add(item);
yield return item;
}
for(;;)
{
foreach(var item in data)
{
yield return item;
}
}
}
}
現在,您可以采用一個序列並將其設為循環的無限序列:
IEnumerable<Foo> mySeq = ...;
IEnumerable<Foo> infMySeq = mySeq.LoopForver();
IEnumerable<Foo> aSelectionOfInfMySeq = infMySeq.Skip(101).Take(5);
您可以實現IEnumerator接口:
class InifniteEnumerator<T> : IEnumerator<T> {
private int index = -1;
private IList<T> innerList;
private int repeatPos;
public InifniteEnumerator(IList<T> innerList, int repeatPos) {
this.innerList = innerList;
this.repeatPos = repeatPos;
}
public T Current {
get {
if (index == -1) {
throw new InvalidOperationException();
}
return this.innerList[index];
}
}
object IEnumerator.Current {
get {
return this.Current;
}
}
public void Dispose() {
}
public bool MoveNext() {
this.index++;
if (this.index == repeatPos) {
this.index = 0;
}
return true;
}
public void Reset() {
this.index = -1;
}
}
然后在GetEnumerator方法中返回它的一個實例:
IEnumerator IEnumerable.GetEnumerator() {
return this.GetEnumerator();
}
public IEnumerator<T> IEnumerable<T>.GetEnumerator() {
return new InifniteEnumerator(this, 100);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.