Wrap ein IEnumerable und Ausnahmen abfangen

8

Ich habe eine Menge Klassen, die Process() -Objekte haben und ihre eigenen Objekte zurückgeben können:

%Vor%

Ich möchte eine Prozessorklasse schreiben, die einen dieser Prozessoren umbrechen kann, und alle nicht abgefangenen Ausnahmen protokollieren, die die umschlossene Methode Process() möglicherweise auslöst. Meine erste Idee war so etwas:

%Vor%

aber das funktioniert nicht, wegen CS1626: Kann keinen Wert liefern in der Körper eines Versuchsblocks mit einer Fangklausel .

Ich möchte also etwas schreiben, das konzeptionell äquivalent ist, aber kompiliert. :-) Ich habe das:

%Vor%

aber das ist komplexer, als ich es mir erhofft habe, und ich bin mir weder ganz sicher, ob es korrekt ist, noch dass es einen viel einfacheren Weg gibt.

Bin ich hier richtig? Gibt es einen einfacheren Weg?

    
Ken 30.09.2010, 23:54
quelle

5 Antworten

4

Eine linq-Erweiterung kann geschrieben werden, um alle Elemente zu überspringen, die eine Ausnahme verursachen, und sie an eine Protokollierungsfunktion weiterzugeben.

%Vor%

Beispiel:

%Vor%     
katbyte 16.04.2014 21:56
quelle
4

Wenn Sie während der Verarbeitung des Ergebnisses einer Enumeration eine Ausnahme behandeln möchten, müssen Sie versuchen, die Logik einfach in Ihre for / while-Schleife zu übernehmen.

Aber Ihr Beispiel liest sich so, als wollten Sie Ausnahmen abfangen und überspringen, die vom Aufzählungsanbieter ausgelöst wurden.

Soweit ich feststellen kann, gibt es in C # keine Möglichkeit, über einen Enumerator zu iterieren und die Exception innerhalb des Enumerators selbst zu überspringen. Wenn der Enumerator eine Ausnahme auslöst, führen alle zukünftigen Aufrufe von MoveNext () zu einer falschen Ausgabe.

Der einfachste Weg zu erklären, warum dies passiert, ist mit diesem einfachen -Enumerable:

%Vor%

Verständlicherweise, wenn wir uns dieses Beispiel ansehen, ist es offensichtlich, dass die geworfene Ausnahme dazu führt, dass dieser ganze Block beendet wird, und die 3. und 4. Yield-Anweisung wird niemals verarbeitet. In der Tat erhalten Sie die übliche Compilerwarnung 'Unreachable code detected' auf der 3. Yield-Anweisung.

Wenn das Aufzählungszeichen komplexer ist, gelten die gleichen Regeln:

%Vor%

Wenn die Ausnahme ausgelöst wird, wird die Verarbeitung dieses Blocks beendet und der Aufrufstapel an den nächsten Ausnahmebehandler übergeben.

ALLE durchführbaren Beispiele, die dieses Problem umgehen, das ich in SO gefunden habe, gehen nicht zum nächsten Element in der Aufzählung, sie brechen bei der ersten Ausnahme.

Um Ausnahme in der Aufzählung zu überspringen, benötigen Sie den Provider, um es zu erleichtern. Dies ist nur wirklich möglich, wenn Sie den Anbieter verschlüsselt haben, oder Sie können den Entwickler kontaktieren, der das getan hat, ist das folgende ein über vereinfachtes Beispiel, wie Sie dies erreichen könnten:

%Vor%

...

%Vor%

Dies erzeugt die folgende Ausgabe:

%Vor%

Ich hoffe, dass dies das Problem für andere Entwickler in der Zukunft aufklärt, da es eine ziemlich allgemeine Idee ist, die wir alle bekommen, sobald wir anfangen, uns in Linq und Enumerationen zu vertiefen. Mächtige Sachen, aber es gibt einige logische Einschränkungen.

    
Chris Schaller 12.01.2016 13:47
quelle
0

Es könnte netter sein, wenn das process -Objekt nur ein Element in der Liste auf einmal verarbeitet (wenn das überhaupt möglich ist), auf diese Weise könnten Sie jede einzelne Ausnahme sammeln und eine AggregateException genau wie die zurückgeben Aufgabe parallele Bibliothek tut.

[Wenn der Prozess auf der Liste als Ganzes ausgeführt wird oder wenn eine einzige Ausnahme den gesamten Prozess abbrechen muss, ist dieser Vorschlag offensichtlich nicht angebracht.]

    
Ian Mercer 01.10.2010 01:15
quelle
-1

Die Schleife und die Ausbeute werden nicht benötigt (zumindest in Ihrem Beispiel). Einfach entfernen Sie sie und es gibt keine Beschränkung mehr auf catch-Blöcke.

%Vor%

Ich gehe davon aus, dass this.processor.Process(incoming) eine Sammlung zurückgibt, die IEnumerable<T> implementiert, also müssen Sie keinen neuen Iterator erstellen. Wenn this.processor.Process(incoming) faul auswertet, dann

%Vor%     
Bear Monkey 01.10.2010 00:35
quelle
-1

Anstatt nur Ihr spezifisches Problem zu lösen, können Sie diese Hilfsfunktionen in Ihrem Toolkit haben:

%Vor%

WithExceptionHandler<T> konvertiert ein IEnumerable<T> in ein anderes, und wenn eine Ausnahme auftritt, wird der onException Callback aufgerufen. Auf diese Weise können Sie Ihre process Funktion wie folgt implementieren:

%Vor%

Auf diese Weise können Sie auch etwas anderes tun, wie die Ausnahme vollständig ignorieren und die Iteration einfach anhalten lassen. Sie können es auch ein wenig anpassen, indem Sie Func<Exception, bool> anstelle von Action<Exception> verwenden und der Ausnahme-Callback entscheiden kann, ob die Iteration fortgesetzt werden soll oder nicht.

    
Earth Engine 09.02.2014 23:09
quelle

Tags und Links