2017-06-13 67 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」的複數。 –

相關問題