对于能够使用“ foreach ”进行迭代的类,它应该实现 IEnumerable 接口。 但为什么这个没有实现的简单类可以迭代?
public class Person
{
public int Age { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public Person() { }
public Person(string firstName, string lastName, int age)
{
Age = age;
FirstName = firstName;
LastName = lastName;
}
public override string ToString()
{
return string.Format("Name: {0} {1}, Age: {2}",
FirstName, LastName, Age);
}
}
当我运行代码时,我没有错误关于使用 Foreach
class Program
{
static void Main(string[] args)
{
UseGenericList();
}
static void UseGenericList()
{
List<Person> people=new List<Person>()
{
new Person("Homer","Simpson",47),
new Person {FirstName = "Marge",LastName ="Simpson",Age = 45},
new Person {FirstName = "Lisa",LastName = "Simpson",Age = 9},
new Person {FirstName = "Bart",LastName = "Simpson",Age = 8}
};
Console.WriteLine("Items in the list:{0}",people.Count);
foreach (Person P in people)
{
Console.WriteLine(P);
}
Console.WriteLine("Inserting new person");
people.Insert(2,new Person {FirstName ="Maggie",LastName = "Simpson",Age = 2});
Console.WriteLine("items in the list{0}",people.Count);
Person[] ArraysOfPeople = people.ToArray();
for (int i = 0; i < ArraysOfPeople.Length; i++)
{
Console.WriteLine("First Name:{0}",ArraysOfPeople[i].FirstName);
}
}
}
为什么?
答案 0 :(得分:8)
您正在使用List<T>
课程来存储Person
集合,其中T
是Person
类。 List<T>
类实现IEnumerable
接口。因此,你可以使用foreach
答案 1 :(得分:4)
首先,Abhishek的答案是完全正确的;您使用的是List<T>
IEnumerable
。
然而,即使它不是 IEnumerable
,它仍然有效。
I refer to this SO answer which goes more in depth
重要的一点:
更重要的是,C#中的
foreach
语句可以在不涉及IEnumerable的情况下工作。编译器有效地对名称GetEnumerator()
,Current
和MoveNext()
进行编译时鸭子输入。这主要是为了允许在泛型之前在C#1中进行强类型(和非装箱)迭代。有关详细信息,请参阅C#3规范的第8.8.4节。
换句话说,只要该类提供了必要的方法,就不需要实现IEnumerable
!
当然,仍然强烈建议简单地实施IEnumerable
,但这在技术上并不是必需的。
答案 2 :(得分:-1)
为了澄清更多,你正在使用的陈述,即
foreach (Person P in people)
{
Console.WriteLine(P);
}
这里的人是人的列表,即List,你的List实现IEnumerable,它有一个名为GetEnumerator的方法
最初,枚举数位于第一个元素之前 集合。 Reset方法也会将枚举器返回 这个职位。在此位置,Current属性未定义。 因此,您必须调用MoveNext方法来推进枚举器 在读取值之前到集合的第一个元素 当前。
Current返回相同的对象,直到MoveNext或 调用重置。 MoveNext将Current设置为下一个元素。
如果MoveNext传递集合的末尾,则枚举器为 位于集合中的最后一个元素和MoveNext之后 返回false。当调查员处于这个位置时,随后 对MoveNext的调用也返回false。如果最后一次调用MoveNext 返回false,当前未定义。将Current设置为第一个 再次收集该元素的元素,您可以调用Reset后跟 MoveNext的。
有关更多非传统的间接学习,请参阅Eric's Blog
您可能认为为了使用foreach循环,该集合 您正在迭代必须实施
IEnumerable
或IEnumerable<T>
。 但事实证明,这实际上并不是一项要求。什么是 要求的是集合的类型必须具有公共方法 名为GetEnumerator,必须返回一些具有public的类型 属性getter名为Current和一个公共方法MoveNext 返回一个布尔。如果编译器可以确定所有这些 如果满足要求,则生成代码以使用这些方法。 只有在不满足这些要求的情况下,我们才会检查是否存在 object实现IEnumerable或IEnumerable。