foreach可以迭代一些.net本来就为我们做好的类型,比如int,string等等
但是如果想迭代自己的类,就必须自己来写了
首先就要先实现IEnumerator的几个方法,和IEnumerable的GetEnumerator()方法
代码
foreach
(person p
in
persons)
{
console.writeline(p)
}
//会解析为
IEnumerator enumerator
=
persons.GetEnumerator();
while
(enumerator.MoveNext())
{
Person p
=
(Person)enumerator.Current;
Console.WriteLine(p);
}
也就是说,foreach循环会调用IEnumerator下的几个方法
他们分别是:public bool MoveNext(),public void Reset(), public object Current属性
顾名思义
代码
public
class
Person
{
public
Person(
string
fName,
string
lName)
{
this
.firstName
=
fName;
this
.lastName
=
lName;
}
public
string
firstName;
public
string
lastName;
}
public
class
People : IEnumerable
{
private
Person[] _people;
public
People(Person[] pArray)
{
//
_people=pArray?????????
_people
=
new
Person[pArray.Length];
for
(
int
i
=
0
; i
<
pArray.Length; i
++
)
{
_people[i]
=
pArray[i];
}
}
///
<summary>
///
接口的实现,返回的是一个PeopleEnum的一个类对象
///
</summary>
///
<returns></returns>
public
IEnumerator GetEnumerator()
{
return
new
PeopleEnum(_people);
}
}
public
class
PeopleEnum : IEnumerator
{
public
Person[] _people;
//
Enumerators are positioned before the first element
//
until the first MoveNext() call.
int
position
=
-
1
;
public
PeopleEnum(Person[] list)
{
_people
=
list;
}
public
bool
MoveNext()
{
position
++
;
return
(position
<
_people.Length);
}
public
void
Reset()
{
position
=
-
1
;
}
public
object
Current
{
get
{
try
{
return
_people[position];
}
catch
(IndexOutOfRangeException)
{
throw
new
InvalidOperationException();
}
}
}
}
class
App
{
static
void
Main()
{
Person[] peopleArray
=
new
Person[
3
]
{
new
Person(
"
John
"
,
"
Smith
"
),
new
Person(
"
Jim
"
,
"
Johnson
"
),
new
Person(
"
Sue
"
,
"
Rabon
"
),
};
People peopleList
=
new
People(peopleArray);
foreach
(Person p
in
peopleList)
{
Console.WriteLine(p.firstName
+
"
"
+
p.lastName);
}
Console.Read();
}
}
总结: 迭代自定义的类,必须实现实现GetEnumerator()方法返回IEnumerator
IEnumerator提供了foreach使用的方法属性
C#2.0有了yield关键字,就不用每次都这样实现IEnumerator接口了
包含yield语句的方法必须返回IEnumerator或者IEnumerable接口
代码
public
class
person
{
private
string
_Name;
public
string
Name {
get
;
set
; }
public
person(
string
name)
{
Name
=
name;
}
public
override
string
ToString()
{
return
this
.Name;
}
}
class
people
{
private
person[] _person;
public
people(person[] person)
{
_person
=
person;
}
public
IEnumerator GetEnumerator()
{
for
(
int
i
=
0
; i
<
_person.Length; i
++
)
{
yield
return
_person[i];
}
}
public
IEnumerable reverse()
{
for
(
int
i
=
_person.Length
-
1
; i
>=
0
; i
--
)
{
yield
return
_person[i];
}
}
}
class
Program
{
static
void
Main(
string
[] args)
{
person[] p
=
new
person[
3
]
{
new
person(
"
John
"
),
new
person(
"
Jim
"
),
new
person(
"
Sue
"
),
};
people pp
=
new
people(p);
foreach
(person pe
in
pp)
{
Console.WriteLine(pe);
}
foreach
(person ppp
in
pp.reverse())
{
Console.WriteLine(ppp);
}
Console.Read();
}
}
我认为yield关键字帮助我们实现了IEnumerator的方法
也可以自己定义迭代的方式,比如以上代码就实现了逆向循环。
参考:C#红皮书