8 Stimmen

Beispiel für die "Verwendung von Ausnahmen zur Steuerung des Flusses"

Wie würde ein Codestück aussehen, das "Ausnahmen für den Kontrollfluss verwendet"? Ich habe versucht, ein direktes C#-Beispiel zu finden, kann es aber nicht. Warum ist das schlecht?

Danke

2voto

Reed Copsey Punkte 536986

Ich arbeite derzeit mit einem Programm eines Drittanbieters, das diese Aufgabe übernimmt. Sie haben eine "Cursor"-Schnittstelle (im Grunde eine IEnumerable-Alternative), bei der die einzige Möglichkeit, dem Programm mitzuteilen, dass man fertig ist, darin besteht, eine Ausnahme auszulösen. Der Code sieht im Wesentlichen so aus:

// Just showing the relevant section
bool finished = false;

public bool IsFinished()
{
    return finished;
}

// Using something like:
// int index = 0;
// int count = 42;

public void NextRecord()
{
    if (finished)
        return;

    if (index >= count)
        throw new APIProgramSpecificException("End of cursor", WEIRD_CONSTANT);
    else
        ++index;
}

// Other methods to retrieve the current value

Unnötig zu erwähnen, dass ich hassen die API - aber es ist ein gutes Beispiel für Ausnahmen für die Flusskontrolle (und eine verrückte Art zu arbeiten).

1voto

Adam Lear Punkte 36637

Ein Beispiel wäre die Verwendung von Ausnahmen, um ein Ergebnis aus einer rekursiven Methode zurückzugeben:

public void Search(Node node, object data)
{
    if(node.Data.Equals(data))
    {
        throw new ResultException(node);
    }
    else
    {
        Search(node.LeftChild, data);
        Search(node.RightChild, data);
    }    
}

So etwas zu tun, ist aus mehreren Gründen ein Problem.

  1. Das ist völlig kontra-intuitiv. Ausnahmen sind für Ausnahmefälle gedacht. Etwas, das wie vorgesehen funktioniert, sollte (so hoffen wir) niemals ein Ausnahmeszenario sein.
  2. Sie können sich nicht immer darauf verlassen, dass eine Ausnahme ausgelöst und an Sie weitergeleitet wird. Wenn der Code, der die Ausnahme auslöst, zum Beispiel in einem separaten Thread läuft, benötigen Sie zusätzlichen Code, um die Ausnahme zu erfassen.
  3. Dies ist ein potenzielles Leistungsproblem. Mit Ausnahmen ist ein Overhead verbunden, und wenn Sie viele Ausnahmen auslösen, können Sie einen Leistungsabfall in Ihrer Anwendung feststellen.

Es gibt einige weitere Beispiele und interessante Diskussionen zu diesem Thema aquí .

Haftungsausschluss: Der obige Code wurde von dem ersten Beispiel auf dieser Wiki-Seite angepasst, um ihn in C# umzuwandeln.

1voto

Jack Punkte 128223

Ich bin kein Freund von C#, aber man kann einige Ähnlichkeiten erkennen zwischen try-catch-finally Anweisungen und normale Kontrollflussanweisungen if-then-else .

Denken Sie daran, wenn Sie throw einer Ausnahme erzwingen Sie die Übergabe Ihrer Kontrolle an den catch Klausel. Wenn Sie also

if (doSomething() == BAD) 
{
  //recover or whatever
}

Man kann sich das ganz einfach im Sinne von try-catch vorstellen:

try
{
  doSomething();
}
catch (Exception e)
{
  //recover or do whatever
}

Das Leistungsstarke an Ausnahmen ist, dass man sich nicht im selben Körper befinden muss, um den Programmfluss zu ändern. Man kann eine Ausnahme auslösen, wann immer man will, mit der Garantie, dass der Kontrollfluss plötzlich abweicht und die catch-Klausel erreicht. Das ist mächtig, aber gleichzeitig auch gefährlich, da man Aktionen ausführen könnte, die am Ende eine Sicherung benötigen, weshalb die finally Anweisung existiert.

Zusätzlich können Sie auch ein Modell while Anweisung, ohne die Bedingung dafür effektiv zu nutzen:

while (!finished)
{
  //do whatever
}

werden können

try
{
  while (true)
  {
     doSomethingThatEventuallyWillThrowAnException();
  }
}
catch (Exception e)
{
  //loop finished
}

1voto

dthorpe Punkte 34584

Ein von einem Partner entwickeltes Modul führte dazu, dass unsere Anwendung sehr lange zum Laden brauchte. Bei näherer Betrachtung suchte das Modul beim Starten der Anwendung nach einer Konfigurationsdatei. Das war an sich nicht weiter schlimm, aber die Art und Weise, wie es dies tat, war unverschämt schlecht:

Für jede Datei im App-Verzeichnis wurde die Datei geöffnet und versucht, sie als XML zu parsen. Wenn eine Datei eine Ausnahme auslöste (weil es sich nicht um XML handelte), wurde die Ausnahme abgefangen, unterdrückt und die nächste Datei versucht!

Als der Partner dieses Modul testete, hatte er nur 3 Dateien im App-Verzeichnis. Die dämliche Suche nach Konfigurationsdateien hatte keine spürbaren Auswirkungen auf den Start der Testanwendung. Als wir es zu unserer Anwendung hinzufügten, befanden sich Hunderte von Dateien im App-Verzeichnis, und die Anwendung fror beim Start fast eine Minute lang ein.

Um dem Ganzen noch die Krone aufzusetzen, war der Name der Konfigurationsdatei, nach der das Modul suchte, vorgegeben und konstant. Es bestand keine Notwendigkeit für eine Dateisuche irgendeiner Art.

Das Genie hat seine Grenzen. Dummheit ist grenzenlos.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X