2017-06-13 74 views
-5

针对一类能够使用“的foreach”进行迭代,它应该实现的IEnumerable接口。 但为什么这个没有实现的简单类可以迭代?为什么这个类不需要实现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); 
     } 
    } 

} 

关于为什么没有错误

+11

因为您正在迭代'List ',您**不是**迭代'Person'。迭代人看起来像'foreach(var personObjectObject)',当然它会失败 –

+1

列表实现IEnumerable –

回答

8

您正在使用List<T>类来存储您的Person集合,其中TPerson类。 List<T>类实现IEnumerable接口。因此,你可以使用foreach

5

首先,阿布舍克的答案是完全正确的;您正在与List<T>这是一个IEnumerable


然而,即使它不是一个IEnumerable,它仍然能工作。

I refer to this SO answer which goes more in depth

最重要的一点:

更重要的是,在C#中foreach语句而不IEnumerable的参与工作。编译器有效地在名称GetEnumerator()CurrentMoveNext()上进行编译时鸭式打字。这主要是为了在泛型之前允许C#1中的强类型(和非装箱)迭代。有关更多详细信息,请参阅C#3规范的8.8.4部分。

换句话说,只要该类提供必要的方法,就不需要实施IEnumerable

当然强烈建议仅执行IEnumerable,但这在技术上并不需要。

0

为了澄清更多的,声明你使用的是IE这里

foreach (Person P in people) 
{ 
    Console.WriteLine(P); 
} 

人是人名单这应该被称为为清楚起见,即清单人民或别的东西,你列表实现IEnumerable其中有一个名为方法GetEnumerator

最初,枚举器位于集合的第一个元素 之前。重置方法还使枚举器返回到 这个位置。在这个位置,Current属性是未定义的。 因此,必须调用MoveNext方法将枚举数 前移到集合的第一个元素,然后才能读取当前的值 Current。

当前返回相同的对象,直到调用MoveNext或 Reset。 MoveNext将Current设置为下一个元素。

如果MoveNext通过集合的末尾,则枚举数为 ,该集合位于集合中的最后一个元素之后,并且MoveNext 返回false。当枚举器在这个位置时,后续的 调用MoveNext也返回false。如果上次调用MoveNext 返回false,则Current未定义。要再次将Current设置为第一个 元素,您可以将Reset设置为 MoveNext。

更多非传统的间接学习参考Eric's Blog

你可能会认为,以使用foreach循环,收集 你迭代必须实现IEnumerableIEnumerable<T>。但事实证明,这实际上并不是一项要求。 需要什么是集合的类型必须有一个名为GetEnumerator的公共方法 ,并且必须返回一些具有公共方法 属性获取器称为Current和公共方法MoveNext 返回一个布尔。如果编译器可以确定满足所有这些要求,则会生成代码以使用这些方法。 只有在不符合这些要求的情况下,我们才会检查 对象是否实现IEnumerable或IEnumerable。

+0

我认为命名是可以的......“people”是“person”的复数。 –

相关问题