久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

C# 常用接口學(xué)習(xí) IEnumerable<T>

 ontheroad96j47 2021-11-08

我們先去看看公開的.Net4.0的源程序中IEnumerable<T>,、IEnumerable,、IEnumerator<T>和IEnumerator這四個(gè)接口是如何聲明的:

需加微信交流群的,,請加小編微信號(hào)zls20210502,,切記備注 加群,,小編將會(huì)第一時(shí)間邀請你進(jìn)群,!目前一群滿員,,只能進(jìn)二群了!

    public interface IEnumerable<out T> : IEnumerable
    {
        new IEnumerator<T> GetEnumerator();
    }

    public interface IEnumerator<out T> : IDisposable, IEnumerator
    {
        new T Current {
            get;
        }
    }

    public interface IEnumerable
    {
        IEnumerator GetEnumerator();
    }

    public interface IEnumerator
    {
        bool MoveNext();
        Object Current {
            get;
        }
    
        void Reset();
    }

一,、接口IEnumerable實(shí)現(xiàn)

1,、建一個(gè)學(xué)生數(shù)據(jù)結(jié)構(gòu)和一個(gè)學(xué)生集合類:

    //student數(shù)據(jù)結(jié)構(gòu)
    class Student
    {
        public int id;
        public string name;
    }

    //student 集合
    class StudentCollection
    {
        public List<Student> students = new List<Student>();
        public void Add(Student student)
        {
            students.Add(student);
        }
    }

公開一個(gè)Add()方法以添加數(shù)據(jù),我們的集合類建立完畢,。下來添加數(shù)據(jù):

        static void Main(string[] args)
        {
            StudentCollection sc = new StudentCollection();
            sc.Add(new Student { id=0,name="Tony"});
            sc.Add(new Student { id=1,name="Micheal"});
            sc.Add(new Student { id =2, name = "Amy" });
            foreach(var s in sc) {...}
        }
    }

當(dāng)我們想用foreach()遍歷的時(shí)候,,編譯器會(huì)告訴我們StudentCollection不包含GetEnumerator,不能用foreach遍歷,。雖然StudentCollection里面有能用遍歷的List<T>,,但我們不想在屬性上迭代,,我們想在類上迭代,不能 foreach(var s in sc.students){...}

現(xiàn)在只有把我們的StudentCollection類改造成能foreach的,。

2,、繼承接口IEnumerable:

當(dāng)我們在類后面加上:IEnumerable后,Visual Studio IDE會(huì)冒出來一個(gè)小黃燈泡,,點(diǎn)進(jìn)去有提示自動(dòng)填充接口的約定,,我們選第一項(xiàng)實(shí)現(xiàn)接口(Visaul Studio是全世界最貼心的IDE!),IDE會(huì)幫我們把SudentCollection改造成以下的:

    class StudentCollection:IEnumerable
    {
        public List<Student> students = new List<Student>();
        public void Add(Student student)
        {
            students.Add(student);
        }

        public IEnumerator GetEnumerator()
        {
            throw new NotImplementedException();
        }
    }

加了一個(gè)返回迭代器的方法GetEnumrator,。下來按照IEnumetator接口的約定來實(shí)現(xiàn)我們的迭代器StudentCollectionEnumerator,,用IDE自動(dòng)補(bǔ)全代碼如下:

    //迭代器
    class StudentCollectionEnumerator : IEnumerator
    {
        public object Current
        {
            get
            {
                throw new NotImplementedException();
            }
        }

        public bool MoveNext()
        {
            throw new NotImplementedException();
        }

        public void Reset()
        {
            throw new NotImplementedException();
        }
    }

我的理解是:Current返回當(dāng)前元素,MoveNext移動(dòng)到下一個(gè),,Reset回到第一個(gè)元素,。但根據(jù)MSDN上面的說法,Reset 方法提供的 COM 互操作性,。它不一定需要實(shí)現(xiàn),;相反,實(shí)施者只需拋出NotSupportedException,。但是,,如果您選擇執(zhí)行此操作,則應(yīng)確保沒有調(diào)用方依賴于Reset功能,。

迭代器工作的原理是:先調(diào)用MoveNext()方法,,然后讀取Current得到元素,直到MoveNext返回false,。

我們需要3個(gè)字段分別放置 元素的位置,、元素、元素集,。改變后的程序如下:

    //迭代器
    class StudentCollectionEnumerator : IEnumerator
    {
        private int _index;
        private List<Student> _collection;
        private Student value;
        public StudentCollectionEnumerator(List<Student> colletion)
        {
            _collection = colletion;
            _index = -1;
        }
         object IEnumerator.Current
        {
            get { return value; }
        }
        public bool MoveNext()
        {
            _index++;
            if (_index >= _collection.Count) { return false; }
            else { value = _collection[_index]; }
            return true;
        }
        public void Reset()
        {
            _index = -1;
        }

    }

首先,,迭代器初始化,引入元素集 _collection,,并把索引 _index設(shè)置成-1,。設(shè)置成-1而不是0是因?yàn)榈魇紫日{(diào)用MoveNext,在MoveNext里面我們先把索引+1指向下一個(gè)元素,,如果索引_index的值初始為0,,則第一個(gè)元素是元素集[1],第二個(gè)元素了,。
其次,,我們要把object Current改成 IEnumerator.Current,這個(gè)是實(shí)現(xiàn)迭代器的關(guān)鍵。返回元素,。(好像有裝箱的行為)
第三,,在MoveNext方法內(nèi)累加索引,并從元素集中讀取元素,。然后讓索引值超出元素集返回個(gè)false值,。
最后,在Reset方法內(nèi)讓索引值為-1,,不過好像直接拋出錯(cuò)誤也成。

迭代器寫好了,,我們在StudentColletion類里面調(diào)用:

class StudentCollection : IEnumerable
    {
        public List students;
        public StudentCollection()
        {
            students = new List();
        }
        public void Add(Student student)
        {
            students.Add(student);
        }
        public IEnumerator GetEnumerator()
        {
            return new StudentCollectionEnumerator(students);
        }
    }

測試運(yùn)行一下,,大功告成!我們實(shí)現(xiàn)了可枚舉的自己的類,。

通過觀察,,發(fā)現(xiàn)迭代器主要就是返回一個(gè)元素對象,而StudentColletion里面的students元素集是List的,,本身就能枚舉,,我們能不能利用這個(gè)不用專門寫迭代器來實(shí)現(xiàn)枚舉呢?
答案是肯定的,我們這樣寫:

    class StudentCollection:IEnumerable
    {
        public List<Student> students = new List<Student>();
        public void Add(Student student)
        {
            students.Add(student);
        }

        public IEnumerator GetEnumerator()
        {
            foreach(var s in students)
            {
                yield return s;
            }
        }
    }

這樣就能實(shí)現(xiàn)枚舉了,,真簡單,,充分利用了.Net給出的各種可枚舉集合,不用再去寫GetEnumerator這種累活了,。

二,、接口IEnumerable<T>實(shí)現(xiàn)

如果我們想寫一個(gè)通用的可foreach的類,用到泛型:

    class MyCollection<T>
    {
        public List<T> mycollection = new List<T>();
        public void Add(T value)
        {
            mycollection.Add(value);
        }
    }

其實(shí)這個(gè)MyCollection類只不過是在List<T>外面封裝了一層,,要實(shí)現(xiàn)IEnumable<T>,,繼承該泛型接口,Visual Studio 的IDE自動(dòng)幫我們補(bǔ)全后,,如下:

    class MyCollection:IEnumerable
    {
        public List mycollection = new List();
        public void Add(T value)
        {
            mycollection.Add(value);
        }
        public IEnumerator GetEnumerator()
        {
            throw new NotImplementedException();
        }
        IEnumerator IEnumerable.GetEnumerator()
        {
            throw new NotImplementedException();
        }
    }

我們直接用上面第二個(gè)簡單的寫法,,改成:

    class MyCollection:IEnumerable
    {
        public List mycollection = new List();
        public void Add(T value)
        {
            mycollection.Add(value);
        }
        public IEnumerator GetEnumerator()
        {
            foreach(var s in mycollection)
            {
                yield return s;
            }
        }
        IEnumerator IEnumerable.GetEnumerator()
        {
            foreach (var s in mycollection)
            {
                yield return s;
            }
        }
    }

測試運(yùn)行:

     static void Main(string[] args)
        {
            MyCollection mc = new MyCollection();
            mc.Add(0);
            mc.Add(1);
            mc.Add(2);
            foreach(var s in mc) { Console.WriteLine(s); }
            Console.ReadKey();
    }

大功告成!
雖然第二種寫法比較投機(jī),,充分利用了.NET Framework給的各種泛型集合可枚舉的特征,。不過我們也自己實(shí)現(xiàn)了一個(gè)GetEnumerator(),了解了枚舉器的工作原理,。本章學(xué)習(xí)目的達(dá)成,。

    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多