要实现集合,我必须完成GeEnumerator()。但是这个函数的返回类型是IEnumerator。怎么做到呢 ? 例如..
class MyList : IEnumerable, IEnumerator
{
private int[] array;
int positino = -1;
public IEnumerator GetEnumerator()
{
for(int i = 0 ; i < array.Length; ++i)
{
yield return array[i];
}
}
}
array [i]是整数而不是IEnumerator类型。该函数如何返回整数?
答案 0 :(得分:2)
使用泛型和IEnumerable int
public class MyList : IEnumerable<int>
{
public MyList()
{
array = new [] { 1, 2, 3, 4, 5, 6, 7};
}
private int[] array;
int positino = -1;
public IEnumerator<int> GetEnumerator()
{
for(int i = 0 ; i < array.Length; ++i)
{
yield return array[i];
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
答案 1 :(得分:2)
该函数如何返回整数
它没有,它yield return
是一个整数。这意味着它可以编译成一个返回IEnumerable
,IEnumerable<int>
,IEnumerator
或IEnumerator<int>
的方法,具体取决于您返回的方法。
yield
关键字是一种便利,可以创建具有相应MoveNext()
,Current
和Dispose
的枚举数,如果它是可枚举的,那么适当的GetEnumerator
。
看看你的方法:
public IEnumerator GetEnumerator()
{
for(int i = 0 ; i < array.Length; ++i)
{
yield return array[i];
}
}
然后这是可以编译的东西,但是为了真正起作用,它需要更多来实际分配给array
。
当我们编译它时,它的结果与我们编写的结果相同:
private class En : IEnumerator<object>
{
private object _current;
private int _state;
public MyList _this;
public int _index;
public bool MoveNext()
{
int state = _state;
switch(state)
{
case 0:
_state = -1;
_index = 0;
break;
case 1:
_state = -1;
if(++_index >= _this.array.Length)
return false;
break;
default:
return false;
}
_current = _this.array[_index];
_state = 1;
return true;
}
public object Current
{
get { return _current; }
}
public void Reset()
{
throw new NotSupportedException();
}
public void Dispose()
{
}
object IEnumerator.Current
{
get { return _current; }
}
public En(int state)
{
_state = state;
}
}
public IEnumerator GetEnumerator()
{
var en = new En(0);
en._this = this;
return en;
}
主要区别在于En
及其字段的名称都不是有效的C#名称,而是有效的.NET名称,因此它不能与程序员使用的任何名称冲突。
这比它需要的更多。它实现了IEnumerator<object>
以及IEnumerator
,但这意味着编译器可以只有IEnumerable<T>
的逻辑,并使用object
作为非T
泛型类型而不是具有单独的逻辑。 _state
比必要的更复杂,但如果yield
- 使用方法比单个循环更复杂,那么_state
的不同值将允许它跟踪哪个部分yield
- 使用与之对应的方法。
总之,在实施IEnumerator
方面做得很好。它比你手工编写一个(比你刚刚使用return array.GetEnumerator();
时要大一些)要大一些,但不是更大,但相反yield
- 使用方法是一个更短,通常这些方法更简单。在例如以下情况下更是如此。您在using
- 使用方法中有一个yield
块,它会在枚举器的Dispose()
中转换为相应的清理。
答案 2 :(得分:1)
请注意,在这种特定情况下,您可以使用数组实现“作弊”而不是真正实现public class MyList : IEnumerable<int>
{
public MyList()
{
array = new[] { 1, 2, 3, 4, 5, 6, 7 };
}
private int[] array;
public IEnumerator<int> GetEnumerator()
{
return ((IEnumerable<int>)array).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
:
!important