为什么这个类不需要实现IEnumerable?

时间:2017-06-13 08:55:59

标签: c#

对于能够使用“ 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);
        }
    }

}

为什么?

3 个答案:

答案 0 :(得分:8)

您正在使用List<T>课程来存储Person集合,其中TPerson类。 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()CurrentMoveNext()进行编译时鸭子输入。这主要是为了允许在泛型之前在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循环,该集合   您正在迭代必须实施IEnumerableIEnumerable<T>。   但事实证明,这实际上并不是一项要求。什么是   要求的是集合的类型必须具有公共方法   名为GetEnumerator,必须返回一些具有public的类型   属性getter名为Current和一个公共方法MoveNext   返回一个布尔。如果编译器可以确定所有这些   如果满足要求,则生成代码以使用这些方法。   只有在不满足这些要求的情况下,我们才会检查是否存在   object实现IEnumerable或IEnumerable。