ForEach 的使用

ForEach 是一個循環結構,但是卻不像 for 一樣使用下標。

它用於 數組 和 集合 的遍歷。

1、數組的遍歷

int[] arr = new int[]{1, 2, 3, 4};
foreach(int element in arr)
{
     Console.WriteLine(element);
}

2、集合的遍歷

using System.Collections;
...

ArrayList list = new ArrayList();
list.Add("hello");
list.Add("guys");

foreach(string e in list)
{
     Console.WriteLine(e);
}

3、泛型集合的遍歷

using System.Collections.Generic;
...

List<int> list = new List<int>();
list.Add(1);
list.Add(3);
list.Add(5);

foreach(int e in list)
{
     Console.WriteLine(e);
}

 

注意:雖然,ForEach 和 For 一樣都是循環結構,但是,它們之間比較大的區別就在於,在Foreach內部是不能對 元素進行修改的,否則會發生編譯錯誤。

ForEach中的變量是ReadOnly變量。

foreach(int e in list)
{
     if(e == 3)
     {
           e = 6; //導致編譯錯誤,不能修改,因爲是 只讀  變量 
     }
}


如果,想要對遍歷 數組或集合中的數據進行修改的話,就 改用 for 循環吧!

 

有時,我們不僅希望能夠在 數組 和集合中使用 Foreach 循環,我們還希望對我們自定義的類使用ForEach循環。

什麼意思呢?就是,對自定義的類的使用 Foreach循環,獲取內部的元素。

 

這時,對於自定義的類,需要去繼承 IEnumerable 或者 IEnumerable<T> 接口,就可以了。

IEnumetable 接口中 只有一個方法IEnumerator GetEnumerator()

由於返回值爲 IEnumerator 意味着,我們還需要去 定義一個類 繼承IEnumerator 接口。

IEnumerator 是所有非泛型枚舉數的基接口。枚舉數可用於讀取集合中的數據,但不能用於修改基礎集合

在IEnumerator中,有三個東西 需要我們去實現,分別是 bool MoveNext(), void Reset(), object Current.

 

public class Person
    {
        string name;
        int age;

        public Person(string name, int age)
        {
            this.name = name;
            this.age = age;
        }

        public override string ToString()
        {
            return this.name + " " + this.age;
        }
    }

    public class People : IEnumerable
    {
        private Person[] people;

        public People(Person[] _people)
        {
            people = new Person[_people.Length];

            for (int i = 0; i < _people.Length; i++)
            {
                people[i] = _people[i];
            }
        }

        public IEnumerator GetEnumerator()
        {
            return (IEnumerator)new PeopleEnumerator(this);
        }

        public class PeopleEnumerator : IEnumerator
        {
            private People p;
            private int position = -1;

            public PeopleEnumerator(People p)
            {
                this.p = p;
            }

            public bool MoveNext()
            {
                if (position < p.people.Length - 1)
                {
                    position++;
                    return true;
                }
                else 
                {
                    return false;
                }
            }

            public void Reset()
            {
                position = -1;
            }

            public object Current
            {
                get { return this.p.people[position]; }
            }
        }

        static void Main()
        {
            Person[] Persons = new Person[] { new Person("kim", 20), new Person("tim", 23) };
            People p = new People(Persons);

            foreach (object obj in p) {
                Person o = (Person)obj;
                Console.WriteLine(o);
            }

            Console.ReadKey(true);
        }
    }

 

其實,我們不用實現 IEnumerable 接口也能夠使用 Foreach循環。只要在 類中有 GetEnumerator()方法和一個具有

MoveNext()、Reset()、Current 這三個東西的類,同樣能夠能行!

代碼示例:

public class Person
    {
        string name;
        int age;

        public Person(string name, int age)
        {
            this.name = name;
            this.age = age;
        }

        public override string ToString()
        {
            return this.name + " " + this.age;
        }
    }

    public class People
    {
        private Person[] people;

        public People(Person[] _people)
        {
            people = new Person[_people.Length];

            for (int i = 0; i < _people.Length; i++)
            {
                people[i] = _people[i];
            }
        }

        public PeopleEnumerator GetEnumerator()
        {
            return new PeopleEnumerator(this);
        }

        public class PeopleEnumerator
        {
            private People p;
            private int position = -1;

            public PeopleEnumerator(People p)
            {
                this.p = p;
            }

            public bool MoveNext()
            {
                if (position < p.people.Length - 1)
                {
                    position++;
                    return true;
                }
                else 
                {
                    return false;
                }
            }

            public void Reset()
            {
                position = -1;
            }

            public Person Current
            {
                get { return this.p.people[position]; }
            }
        }

        static void Main()
        {
            Person[] Persons = new Person[] { new Person("kim", 20), new Person("tim", 23) };
            People p = new People(Persons);

            foreach (Person mate in p){
                Console.WriteLine(mate);
            }

            Console.ReadKey(true);
        }
    }

上例中,沒有再繼承 IEnumerable 接口,但是得到了相同的結果。但是書上說,這個還能夠改進,兩者同時使用。

但是,我不太懂它的含義就,暫且擱置!


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章