2015-06-20 66 views
1

爲了實現集合,我必須完成GeEnumerator()。但是這個函數的返回類型是IEnumerator。如何做呢 ? 例如..public IEnumerator GetEnumerator()的返回類型?

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]; 
     } 
    } 
} 

陣列[i]是整數IEnumerator的類型。這個函數如何返回整數?

+0

我認爲這段代碼編譯和工作。原則上你理解收益率回報是什麼?你遇到什麼問題? – usr

+1

您應該閱讀關於C#中的「yield」:https://msdn.microsoft.com/en-us/library/9k7k7cf0.aspx – MarcinJuraszek

回答

2

哪有此函數返回整數

它並不是,它是一個整數。這意味着它可以被編譯成一個方法,返回IEnumerable,IEnumerable<int>,IEnumeratorIEnumerator<int>,這取決於你的方法返回的方法。

yield關鍵字是一個方便,允許創建一個枚舉與適當MoveNext()CurrentDispose,如果它是一個枚舉再適當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 -using方法比單個循環更復雜,那麼_state的不同值將允許它跟蹤它所對應的那個yield的哪一部分。

總的來說,它在實施IEnumerator方面做得很好。這比你手動編碼一個要大一些(而且明顯大於剛剛使用return array.GetEnumerator();時),但不是很大,但相反yield-使用方法要短得多,通常這些方法更簡單。在例如如下情況下更是如此:您在yield中使用using塊,這種方法在枚舉器的Dispose()中變爲適當的清理。

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

注意,在這種特定的情況下,你可以 「欺騙」,並沒有真正實現GetEnumerator(),使用數組實現:

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(); 
    } 
}