yield return-Anweisung in einem using () {} -Block Dispose vor der Ausführung
Ich geschrieben habe, meine eigenen Daten-layer zu persistieren, um eine bestimmte Datei, und ich habe abstrahiert, es mit einem benutzerdefinierten DataContext-Muster.
Diese beruhen alle auf dem .NET 2.0-Framework (gegebenen Randbedingungen für den Ziel-server), so auch wenn einige es vielleicht Aussehen wie LINQ-to-SQL nicht! Ich habe gerade implementiert eine ähnliche Daten-Muster.
Siehe Beispiel unten zum Beispiel an eine situation, die ich noch nicht erklären.
Um alle Instanzen von Tier - ich mache das und es funktioniert
public static IEnumerable<Animal> GetAllAnimals() {
AnimalDataContext dataContext = new AnimalDataContext();
return dataContext.GetAllAnimals();
}
Sowie die Umsetzung der GetAllAnimals () - Methode in der AnimalDataContext() unten
public IEnumerable<Animal> GetAllAnimals() {
foreach (var animalName in AnimalXmlReader.GetNames())
{
yield return GetAnimal(animalName);
}
}
Den AnimalDataContext() implements IDisposable-da hab ich ein XmlTextReader-in dort, und ich möchte, um sicherzustellen, wird es gereinigt, bis schnell.
Wenn ich nun wickeln Sie den ersten Aufruf innerhalb einer using-Anweisung wie so
public static IEnumerable<Animal> GetAllAnimals() {
using(AnimalDataContext dataContext = new AnimalDataContext()) {
return dataContext.GetAllAnimals();
}
}
und setzen Sie einen break-point in die erste Zeile der AnimalDataContext.GetAllAnimals () - Methode und eine weitere break-point bei der ersten Zeile, in der AnimalDataContext.Dispose () - Methode, und führen Sie...
die Dispose () - Methode zum ERSTEN mal aufgerufen wird, so dass AnimalXmlReader.GetNames() gibt "Objektverweis nicht auf die Instanz des Objekts" Ausnahme, weil AnimalXmlReader wurde auf null gesetzt, in der Dispose () -???
Irgendwelche Ideen? Ich habe eine Ahnung, dass seine im Zusammenhang mit Rendite nicht erlaubt ist, genannt werden innerhalb eines try-catch-block, der mit gerecht wird, einmal zusammengestellt...
InformationsquelleAutor der Frage Neil Fenwick | 2009-10-08
Du musst angemeldet sein, um einen Kommentar abzugeben.
Beim Aufruf
GetAllAnimals
es eigentlich nicht ausführen jeder code, bis Sie aufzählen der zurückgegebene IEnumerable-Schnittstelle in einer foreach-Schleife.DataContext entsorgt werden, sobald das wrapper-Methode zurück, bevor Sie aufzählen, die IEnumerable.
Die einfachste Lösung wäre, um die wrapper-Methode, die einen iterator, als auch, wie diese:
Diese Weise wird die using-Anweisung erstellt werden, in der äußere iterator, und es wird nur entsorgt werden, wenn der äußere iterator entsorgt.
Andere Lösung wäre aufzählen, die IEnumerable in der wrapper. Der einfachste Weg, dies zu tun wäre, um wieder eine
List<Animal>
wie diese:Beachten Sie, dass dieser verliert den Vorteil der verzögerten Ausführung, so wird es um alle Tiere, auch wenn Sie diese nicht benötigen.
InformationsquelleAutor der Antwort SLaks
Der Grund dafür ist, dass die GetAllAnimals Methode nicht wieder ein colleciton der Tiere. Es gibt ein enumerator, der fähig ist, die Rückkehr ein Tier zu einem Zeitpunkt.
Zurück, wenn man das Ergebnis aus der GetAllAnimals Aufruf innerhalb der using-block, Sie einfach nur wieder den Zähler. Der using-block verfügt über die Daten, Kontext, bevor die Methode beendet wird, und an diesem Punkt wird der enumerator noch nicht gelesen haben, Tieren. Wenn Sie dann versuchen, verwenden Sie den enumerator, es können nicht alle Tiere aus den Daten-Kontext.
Ist ein workaround, um die GetAllAnimals Methode auch erstellen eines Enumerators. So des using-Blocks nicht geschlossen werden, bis Sie aufhören, dass enumerator:
InformationsquelleAutor der Antwort Guffa