pl: Mehrere Instanzen einer Exception Class

s. Thema. Ist das möglich in PLs die nicht Perl sind?

Bitte mal um Hinweise.

  1. Tach!

    s. Thema. Ist das möglich in PLs die nicht Perl sind?

    Natürlich, Exceptions sind grundlegend Objekte und Klassen wie alle anderen auch, zumindest unter PHP und C#.

    Ein Anwendungsfall ist, man hat eine Komponente mit einer bestimmten Aufgabe. Zum Erledigen dieser Aufgabe muss sie auf Funktionalität des Frameworks/Systems zugreifen. Dabei tritt eine Exception auf. Die Komponente fängt sie zwar, kann aber nicht angemessen darauf reagieren und gibt sie an den Aufrufer durch. Mitunter wird dann eine neue Exception erzeugt und die eigentliche Exception in der Eigenschaft InnerException weitergegeben.

    So passiert das beim Entity Framework von .NET, das ist ein ORM. Das EF kann diverse Datenbanktreiber ansprechen, und jeder von denen wirft eigene Exceptiontypen. Das EF möchte aber gern eine einheitliche Exception liefern und so erzeugt es eine neue Exception vom Typ à la EntityFrameworkException und hängt die eigentliche Exception (SqlException, MysqlException, SqliteException, ...) als InnerException an. Der Aufrufer fängt also einen definierten Typ statt x verschiedener, und wenn er will, kann er trotzdem die InnerException auswerten.

    dedlfix.

  2. Hallo pl,

    wie man es sinnvoll in Perl oder JavaScript handhabt weiß ich nicht. Dort ist man frei im geworfenen Wert und kann sich ein Konstrukt bauen, wo Exception-Objekte nur einmal erzeugt und dann immer wieder verwendet werden. Ich würde es aber nicht für eine gute Praxis halten. Das kann aber ein Vorurteil sein, dass ich aus anderen Sprachen habe. Aber du wolltest ja gar nicht über Perl reden 😀.

    In PHP, C#, Java ist es üblich, für jeden throw ein neues Exception-Objekt zu erzeugen. Ich müsste es ausprobieren, ob ein throw oldException überhaupt möglich ist oder von der Laufzeitumgebung abgewiesen wird. Habe ich nur leider keine Zeit für dieses Wochenende.

    Bei sogenannten inneren Exceptions hast Du auch für eine Fehlersituation mehrere Exception-Objekte gleichzeitig. Beispielsweise habe ich eine C# Funktion, die einen SQL-Zugriff macht. Der fliegt aus der Kurve und ich bekomme vom SQL Treiber eine SqlException. Die hat als innere Exception eine NetworkException, weil der SQL Treiber nämlich den Server nicht erreichen konnte. Anderes Beispiel: die FaultException aus WCF (Windows Communication Foundation), die auftritt wenn ein gerufener Service eine Exception wirft. Die wird von WCF als Service-Fault behandelt, der Client bekommt eine FaultException und darin ist als Testhilfe ein Klon der am Server geworfenen eigentlichen Exception als InnerException enthalten. Sollte natürlich in Produktion nicht vorkommen, das ist ein Knowledge Leak über die Servicestruktur.

    Ich hatte schon InnerException-Ketten von 4 Exceptions - das ist dann zwar nicht mehr übersichtlich, aber man kann die Fehlerherkunft schön verfolgen.

    Rolf

    --
    sumpsi - posui - clusi
    1. Tach!

      In PHP, C#, Java ist es üblich, für jeden throw ein neues Exception-Objekt zu erzeugen. Ich müsste es ausprobieren, ob ein throw oldException überhaupt möglich ist oder von der Laufzeitumgebung abgewiesen wird.

      In C# kann man Exceptionobjekte wie andere Objekte auch erzeugen. Das ist nicht an ein throw gebunden. Das throw fügt dem übergeben Objekt den Stacktrace hinzu. Zudem kann man ein einzelnes throw; in den Catch-Block schreiben und es wirft die bereits bestehende, gefangene Exception weiter, inklusive neuem Stacktrace.

      Auch PHP arbeitet vergleichbar (braucht aber throw $exobject; für einen Rethrow).

      dedlfix.

      1. Hallo dedlfix,

        wo du das so sagst.... stimmt. Ich habe schon mal so was gebaut

        catch (FooException foo) {
           // do something about foo
           throw foo;
        }
        

        was natürlich ein falscher rethrow ist. Aber das gab nur einen unvollständigen Stacktrace, keinen Laufzeitfehler.

        Rolf

        --
        sumpsi - posui - clusi
  3. Ergänzung: Wenn es von einer EXClass mehrere Instanzen gibt, müsste man die alle durchgehen im catch() Block.

    Ich frage, weil ich derzeit eine diesbezügliche Erweiterung für Perl entwickle aber nicht als Instanziierbare ExceptionSuperClass sondern als Trait. So sind die Namen der eigenen Exceptionklassen nur virtuell. Siehe Anwendung:

    use throw; # Trait
    
    $, = "\n";
    my $main = bless{};
    
    try{
        $main->throw('MyExClass',"Invalid!");
    }
    catch{
        my $exa = $main->caught('MyExClass');
        print $exa->error, $exa->trace;
    };
    

    .

    1. Tach!

      Ergänzung: Wenn es von einer EXClass mehrere Instanzen gibt, müsste man die alle durchgehen im catch() Block.

      Nein, nicht in C# oder PHP. Da gibt man in der catch-Klausel an, welche Exceptionklasse man fangen möchte.

      Vielleicht nochmal zur Klarstellung, geworfen werden kann in beiden genannten Systemen immer nur eine Exception, genauer gesagt ein Exception-Objekt. Aber Exception-Objekte können beliebig viele erstellt werden. Deine Fragestellung, scheint mir, entspricht nicht dem, was du eigentlich wissen wolltest.

      dedlfix.

      1. Tach!

        Ergänzung: Wenn es von einer EXClass mehrere Instanzen gibt, müsste man die alle durchgehen im catch() Block.

        Nein, nicht in C# oder PHP. Da gibt man in der catch-Klausel an, welche Exceptionklasse man fangen möchte.

        Nochmal nachgefragt: Kommt da nur eine Instanz zurück?

        Vielleicht nochmal zur Klarstellung, geworfen werden kann in beiden genannten Systemen immer nur eine Exception, genauer gesagt ein Exception-Objekt. Aber Exception-Objekte können beliebig viele erstellt werden.

        Meine Frage ist, ob das mehrere Exceptionobjekte einer Klasse sein können.

        MfG

        1. Tach!

          Ergänzung: Wenn es von einer EXClass mehrere Instanzen gibt, müsste man die alle durchgehen im catch() Block.

          Nein, nicht in C# oder PHP. Da gibt man in der catch-Klausel an, welche Exceptionklasse man fangen möchte.

          Nochmal nachgefragt: Kommt da nur eine Instanz zurück?

          Wie gesagt, man kann immer nur ein einzelnes Exception-Objekt werfen. Das kann aber bei Bedarf andere Exception-Objekte in seinen Eigenschaften referenzieren. Ein catch fängt jedoch immer nur das eine geworfene Objekt.

          Vielleicht nochmal zur Klarstellung, geworfen werden kann in beiden genannten Systemen immer nur eine Exception, genauer gesagt ein Exception-Objekt. Aber Exception-Objekte können beliebig viele erstellt werden.

          Meine Frage ist, ob das mehrere Exceptionobjekte einer Klasse sein können.

          Man kann wie von jeder anderen Klasse auch beleibig viele Objekte erstellen, aber das spielt im try-catch-Handling keine Rolle, weil immer nur ein einzelnes Exception-Objekt geworfen und gefangen wird.

          dedlfix.

          1. Ok, dann ist hiermit mein

            # Trait for Handle Excepions via virtuell Exception Classes
            

            soweit fertig. Danke für Eure Antworten und schönes Wochenende 😉

            1. Ok, dann ist hiermit mein

              # Trait for Handle Excepions via virtuell Exception Classes
              

              soweit fertig. Danke für Eure Antworten und schönes Wochenende 😉

              HERZLICHEN GLÜHSTRUMPF!

      2. problematische Seite

        In Perl ist es übrigens möglich, beliebig viele Exceptions zu werfen ohne darauf reagieren zu müssen. Nämlich dann wenn jede einzelne Exception mit eval aufgefangen wird:

        # Klassisch mit eval
        eval{ die 123 }; # lost
        eval{ $m->throw('ExA', 'Ex A: Invalid', 1) };
        eval{ $m->throw('ExB', 'Ex B: Ungültig') };
        eval{ die 234 }; # always overwrites $@
        

        Wenn es mehrere eval{}-Blöcke gibt in denen Exceptions aufgetreten sind, wäre auf die herkömmliche Art und Weise $@ überschrieben worden. Erst eine Klassifizierung hebt diesen Nachteil auf. Mit meiner Entwicklung ist es möglich, sämtliche derart aufgefangene Exceptions wiederzufinden.

        Ansonsten kann es auch in Perl in einem eval{} oder try{} Block nur eine Exception geben, die zwar aufgefangen wird, jedoch werden alle danach innerhalb desselben Blocks notierten Anweisungen nicht mehr ausgeführt.

        So macht bspw. ein INSERT-Statement ja auch keinen Sinn wenn die Verbindung weggebrochen ist.

        MfG

        1. problematische Seite

          Tach!

          In Perl ist es übrigens möglich, beliebig viele Exceptions zu werfen ohne darauf reagieren zu müssen. Nämlich dann wenn jede einzelne Exception mit eval aufgefangen wird:

          Wenn du jede einzeln fangen muss, damit es nicht zum Programmabbruch kommt, kannst du auch nicht beliebig viele gleichzeitig werfen. Insofern sehe ich hier kein grundlegend anderes Verhalten als bei C# und PHP.

          dedlfix.

          1. problematische Seite

            Mir gings eigentlich nur darum, den Sinn einer Klassifizierung in Sachen Exceptions zu verdeutlichen.