Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi for..in erlaubt kein "raise" im Exception-Handler, for..to hingegen schon (https://www.delphipraxis.net/196963-erlaubt-kein-raise-im-exception-handler-hingegen-schon.html)

Der schöne Günther 4. Jul 2018 09:58

Delphi-Version: 5

for..in erlaubt kein "raise" im Exception-Handler, for..to hingegen schon
 
Ist hier wieder dunkle Compiler-Magic am Werk? Konstruierter Fall: Ich habe den Fall dass eine Methode entweder eine
Delphi-Quellcode:
EProgrammerNotFound
wirft oder eine
Delphi-Quellcode:
EAggregateException
mit einem Sack an Exceptions da drin.

Wenn ich nur EProgrammerNotFound-Exceptions bekomme ist alles in Butter und kann die behandeln. Ist noch etwas anderes dabei möchte ich die Exception weiter nach oben geben.

Es sieht so aus:

Delphi-Quellcode:
uses System.SysUtils, System.Threading
Delphi-Quellcode:
procedure p();
var
   ex: Exception;
begin
   try
      // do something amazing
   except
      on EProgrammerNotFound do
         findNewProgrammer();
      on e: EAggregateException do
         begin
            for ex in e do
               if (not (ex is EProgrammerNotFound)) then
                  raise; // E2145
            findNewProgrammer();
         end;
   else
      raise;
   end;
end;
Das klappt nur in der Theorie, denn der Compiler streicht das
Delphi-Quellcode:
raise
an und meint:

E2145 Wiederhervorrufen einer Exception ist nur im Exception-Handler möglich

Schreibe ich es hingegen um dass statt einem for..in ein klassisches for..x..to..y zum Einsatz kommt hat niemand etwas dagegen:

Delphi-Quellcode:
procedure p();
var
   ex: Exception;
   exIndex: NativeInt;
begin
   try
      // do something amazing
   except
      on EProgrammerNotFound do
         findNewProgrammer();
      on e: EAggregateException do
         begin
            for exIndex := 0 to Pred(e.Count) do
               if (not (e.InnerExceptions[exIndex] is EProgrammerNotFound)) then
                  raise;
            findNewProgrammer();
         end;
   else
      raise;
   end;
end;

Warum ist das so?

TiGü 4. Jul 2018 10:15

AW: for..in erlaubt kein "raise" im Exception-Handler, for..to hingegen schon
 
Fixed!

Delphi-Quellcode:
program Project5;

{$APPTYPE CONSOLE}

{$R *.res}


uses
  System.SysUtils,
  System.Threading;

procedure findNewProgrammer;
begin
  Writeln('Can not find anyone!');
end;

procedure p();
var
  ex: Exception;
begin
  try
    raise EProgrammerNotFound.Create('FooBar');
  except
    on E: EProgrammerNotFound do
    begin
      findNewProgrammer();
    end;

    on E: EAggregateException do
    begin
      for ex in E do
      begin
        if (not(ex is EProgrammerNotFound)) then
        begin
          raise ex; // Solved: E2145
        end;
      end;
      findNewProgrammer();
    end;
    else
      raise
  end;
end;

begin
  try
    p;
    { TODO -oUser -cConsole Main : Insert code here }
  except
    on E: Exception do
    begin
      Writeln(E.ClassName, ': ', E.Message);
    end;
  end;
  Readln;

end.

Uwe Raabe 4. Jul 2018 10:23

AW: for..in erlaubt kein "raise" im Exception-Handler, for..to hingegen schon
 
Müsste das dann nicht
Delphi-Quellcode:
raise E
heißen? Sonst fallen ja die anderen Exceptions im Aggregat unter den Tisch.
Delphi-Quellcode:
        if (not(ex is EProgrammerNotFound)) then
        begin
          raise E; // Solved: E2145
        end;

Der schöne Günther 4. Jul 2018 10:25

AW: for..in erlaubt kein "raise" im Exception-Handler, for..to hingegen schon
 
Alles klar, man muss es explizit angeben.

Und richtig, wenn schon, dann würde ich die gesamte EAggregateException und nicht eine einzelne aus dem Sack raisen wollen.

Danke an alle! :thumb:

himitsu 4. Jul 2018 10:49

AW: for..in erlaubt kein "raise" im Exception-Handler, for..to hingegen schon
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1406482)
Alles klar, man muss es explizit angeben.

Dann hoffe ich die haben den anderen "Bug" behoben.

Wenn du eine Exception reraisest, welche noch bei der Exceptionbehandlung Registriert ist, dann knallte es immer.


Delphi-Quellcode:
except
  on E: ... do
    raise;
end;
Delphi-Quellcode:
except
  on E: ... do
    raise E; << hier knallte es dann beim END, Freigabe von "internen" E und später wieder auf das neue "E" zugreigen, was aber das Selbe ist
end;
Delphi-Quellcode:
except
  on E: ... do
    raise Exception(AcquireExceptionObject); << Deregistrieren und dann das abgelöste Exception-Objekt wiederverwenden
end;

Der schöne Günther 4. Jul 2018 12:25

AW: for..in erlaubt kein "raise" im Exception-Handler, for..to hingegen schon
 
Stimmt, danke für die Warnung. :thumb:

Das ist nach wie vor so und natürlich absolut tödlich. Die Exception wird ja am Ende des try..except freigegeben.


Im Endeffekt frage ich mich aber weiterhin weshalb es bei einem for..in angemeckert wurde und bei einem for..x..to..y nicht.

himitsu 4. Jul 2018 13:15

AW: for..in erlaubt kein "raise" im Exception-Handler, for..to hingegen schon
 
Eventuell wird bei diesem FOR-IN das nach dem DO als anoyme Methode implementiert?


Nja, es ist auch sooooo schwer im RAISE auf E=Self zu prüfen, also da entweder das dann nur als RAISE zu machen oder vorher intern das AcquireExceptionObject/ReleaseExceptionObject auszuführen.
Auch nervt es, dass die "IMMER" die SystemException auslösen, und das ohne zu prüfen, ob jemand im Try-Except den Message-Text geändert hat, welches dabei verloren geht.


Alle Zeitangaben in WEZ +1. Es ist jetzt 05:28 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz