In dem Bemühen zu entmystifizieren Ich werde vermeiden, über Iteratoren zu sprechen, da sie selbst Teil des Mysteriums sein könnten.
Die Renditerückgabe- und Renditebrechungsanweisungen werden am häufigsten verwendet, um eine "verzögerte Bewertung" der Sammlung bereitzustellen.
Dies bedeutet, dass, wenn Sie den Wert einer Methode erhalten, die Rendite zurückgibt, die Sammlung von Dingen, die Sie versuchen zu erhalten, noch nicht zusammen existieren (es ist im Wesentlichen leer). Wenn Sie sie durchlaufen (mit foreach), führt sie die Methode zu diesem Zeitpunkt aus und ruft das nächste Element in der Enumeration ab.
Bestimmte Eigenschaften und Methoden führen dazu, dass die gesamte Enumeration sofort ausgewertet wird (z. B. "Count").
Hier ist ein kurzes Beispiel für den Unterschied zwischen einer Sammlung Rückkehr und Rückkehr Ausbeute:
string[] names = { "Joe", "Jim", "Sam", "Ed", "Sally" };
public IEnumerable<string> GetYieldEnumerable()
{
foreach (var name in names)
yield return name;
}
public IEnumerable<string> GetList()
{
var list = new List<string>();
foreach (var name in names)
list.Add(name);
return list;
}
// we're going to execute the GetYieldEnumerable() method
// but the foreach statement inside it isn't going to execute
var yieldNames = GetNamesEnumerable();
// now we're going to execute the GetList() method and
// the foreach method will execute
var listNames = GetList();
// now we want to look for a specific name in yieldNames.
// only the first two iterations of the foreach loop in the
// GetYieldEnumeration() method will need to be called to find it.
if (yieldNames.Contains("Jim")
Console.WriteLine("Found Jim and only had to loop twice!");
// now we'll look for a specific name in listNames.
// the entire names collection was already iterated over
// so we've already paid the initial cost of looping through that collection.
// now we're going to have to add two more loops to find it in the listNames
// collection.
if (listNames.Contains("Jim"))
Console.WriteLine("Found Jim and had to loop 7 times! (5 for names and 2 for listNames)");
Dies kann auch verwendet werden, wenn Sie einen Verweis auf die Enumeration erhalten müssen, bevor die Quelldatenwert haben. Zum Beispiel, wenn die Namen Sammlung nicht vollständig war Anfang mit
string[] names = { "Joe", "Jim", "Sam", "Ed", "Sally" };
public IEnumerable<string> GetYieldEnumerable()
{
foreach (var name in names)
yield return name;
}
public IEnumerable<string> GetList()
{
var list = new List<string>();
foreach (var name in names)
list.Add(name);
return list;
}
var yieldNames = GetNamesEnumerable();
var listNames = GetList();
// now we'll change the source data by renaming "Jim" to "Jimbo"
names[1] = "Jimbo";
if (yieldNames.Contains("Jimbo")
Console.WriteLine("Found Jimbo!");
// Because this enumeration was evaluated completely before we changed "Jim"
// to "Jimbo" it isn't going to be found
if (listNames.Contains("Jimbo"))
// this can't be true
else
Console.WriteLine("Couldn't find Jimbo, because he wasn't there when I was evaluated.");
ziemlich Duplikat: http://stackoverflow.com/questions/39476/what-is-the-yield- Stichwort-verwendet-für-in-c –
okay, das könnte ähnlich sein. Aber die Antworten hier sind anders, viel besser auf diese Frage abgestimmt und besser (w.r.t diese Frage) als die in diesem Beitrag. – Sandbox
Darf ich an dieser Stelle eine Frage stellen? Wann immer ein Typ IEnumerable <> zurückgibt, was bedeutet, dass ich es iterieren kann, oder? Weil es die Methode GetEnumerator() hat? Vielen Dank. – Tarik