C# 枚舉器和可枚舉類型

在C#中能夠使用foreach語句遍歷數(shù)組和List等對象的原因就在于這些對象是可枚舉類型,這些可枚舉類型能夠獲取枚舉器,而枚舉器能夠自動獲取對象中的每一個元素。

什么是可枚舉類型?
實(shí)現(xiàn)了IEnumerable中的GetEnumerator方法的類型就是可枚舉類型,從方法名字中就可以知道,用于獲取枚舉器,枚舉器包含集合中的元素信息。

    public interface IEnumerable
    {
        //
        // 摘要:
        //     返回循環(huán)訪問集合的枚舉數(shù)。
        //
        // 返回結(jié)果:
        //     可用于循環(huán)訪問集合的 System.Collections.IEnumerator 對象。
        [DispId(-4)]
        IEnumerator GetEnumerator();
    }

什么是枚舉器?
實(shí)現(xiàn)了IEnumerator接口就是枚舉器,可以依次返回集合中的元素,該接口有一個屬性和兩個方法:
Current,這是一個只讀的object類型屬性,可以返回任何類型,用于獲取集合中的當(dāng)前元素。
MoveNext,這是一個方法,用于將枚舉數(shù)推進(jìn)到集合的下一個元素,如果已是最后一項(xiàng)則返回false。
Reset,這是一個方法,將枚舉數(shù)設(shè)置為其初始位置,該位置位于集合中第一個元素之前。

//
// 摘要:
//     支持對非泛型集合的簡單迭代。
[ComVisible(true)]
[Guid("496B0ABF-CDEE-11d3-88E8-00902754C43A")]
public interface IEnumerator
{
    //
    // 摘要:
    //     獲取集合中的當(dāng)前元素。
    //
    // 返回結(jié)果:
    //     集合中的當(dāng)前元素。
    object Current { get; }

    //
    // 摘要:
    //     將枚舉數(shù)推進(jìn)到集合的下一個元素。
    //
    // 返回結(jié)果:
    //     如果枚舉數(shù)已成功地推進(jìn)到下一個元素,則為 true;如果枚舉數(shù)傳遞到集合的末尾,則為 false。
    //
    // 異常:
    //   T:System.InvalidOperationException:
    //     The collection was modified after the enumerator was created.
    bool MoveNext();
    //
    // 摘要:
    //     將枚舉數(shù)設(shè)置為其初始位置,該位置位于集合中第一個元素之前。
    //
    // 異常:
    //   T:System.InvalidOperationException:
    //     The collection was modified after the enumerator was created.
    void Reset();
}

如果自定義類實(shí)現(xiàn)了可枚舉類型接口和枚舉器接口,便可以使用foreach語句進(jìn)行遍歷了。
實(shí)現(xiàn)可枚舉類型

class SupperStar : IEnumerable
    {
        string[] Names = { "周杰倫", "王力宏", "林俊杰", "李榮浩"};
        public IEnumerator GetEnumerator()
        {
            return new NameEnumerator(Names);
        }
    }

實(shí)現(xiàn)枚舉器

class NameEnumerator : IEnumerator
    {
        string[] _names;
        int _position = -1;

        public NameEnumerator(string[] names)
        {
            _names = new string[names.Length];
            for(int i = 0; i < names.Length; i++)
            {
                _names[i] = names[i];
            }
        }
        /// <summary>
        /// 當(dāng)前元素屬性
        /// </summary>
        public object Current
        {
            get
            {
                if (_position == -1)
                    throw new InvalidOperationException();
                if (_position >= _names.Length)
                    throw new InvalidOperationException();

                return _names[_position];
            }
        }
        /// <summary>
        /// 移動到下一項(xiàng)
        /// </summary>
        /// <returns></returns>
        public bool MoveNext()
        {
            //判斷是否能移動到下一項(xiàng)
            if (_position < _names.Length - 1)
            {
                _position++;
                return true;
            }
            else
                return false;
        }
        /// <summary>
        /// 重置就是把位置參數(shù)重新賦值為-1
        /// </summary>
        public void Reset()
        {
            _position = -1;
        }
    }

使用foreach語句進(jìn)行遍歷

static void Main(string[] args)
 {
       SupperStar star = new SupperStar();
       foreach(var name in star)
       {
            Console.WriteLine(name);
        }
        Console.ReadKey();
 }

以上使用的枚舉類型接口和枚舉器接口都是非泛型版本,在C#使用較多的是泛型版本的IEnumerable<T>和IEnumerator<T>,使用方法差不多,但有一些區(qū)別。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容