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 接口,但是得到了相同的结果。但是书上说,这个还能够改进,两者同时使用。
但是,我不太懂它的含义就,暂且搁置!