It has been quite some time since I wrote the Catch Me If You Can post about the inability of LLVM-backed compilers to catch non-call hardware exceptions. In other words, hardware exceptions raised by code written in the same block as the try...except exception handler. Since then, more LLVM-backed compilers have been added to Delphi, and with those, more reasons to change common coding practices... but still, very few developers know about the issue. The original article covered only try...except exception handlers, and exploring what exactly happens with implicit and explicit try...finally handlers was left as an exercise to the readers and to some future, now long overdue, post. And Now: All Hell Breaks Loose When you read about non-call hardware exceptions not being caught by an immediate try...except block, the implications might not look too serious. After all, while plenty of code can raise exceptions, try...except handlers are not that frequently used in places, as mo
Here's some questions in advance for you (which I'll have to catch on the replay (hint, hint) due to timezones).
ReplyDeleteWhat's your thoughts on The Wiert Corner's aversion to using AfterConstruction? (see his blog post 2021/03/23)
For method parameters what data types do you make const rather than leaving them as a ordinary value parameter? These days I'm using const routinely for strings, interfaces and anonymous methods. I had started doing it for TObject descendants when there was the possibility of my code being run under ARC but I've since removed the consts from those.
I forgot about records. I routinely const those as well.
DeleteAfterConstruction is safe and IMO not used enough. Modifying base class and adding additional virtual DoCreate method is fine, too, if you have base class and you have reasons for not making constructor virtual. But, I would still prefer using it more for configuration than for constructing instances - in other words for final setup after you know all pieces of the object are fully constructed, but that also depends on particular use case. If you need speed, then using AfterConstruction rather than adding new virtual methods is faster.
DeleteThe only part where you need to be careful with AfterConstruction is with reference counted classes and triggering reference counting inside AfterConstruction after you called inherited method - that will cause self destruction of the object. See: https://dalijap.blogspot.com/2019/12/self-destructing-object-instance.html
Also, regardless of the exceptions raised in AfterConstruction, full cleanup will run including BeforeDestruction and Destroy. So that part was not fully correct at least not for newer versions. In Delphi 7 BeforeDestruction is not called, but destructor is. In XE4+ both BeforeDestruction and Destroy are called.
Anyway, since destructor must be able to handle cleanup of partially constructed objects anyway, BeforeDestruction is necessary only seldom, as anything created there can be cleaned up in Destroy.
For parameters, I am following same logic you do. I also use it for larger records if I don't need to modify it - it allows compiler to optimize and avoid copying the whole record.
I couldn't help myself answering your questions here... but I will mention that topic on the webinar, too :)
Delete