Jump to content

Leaderboard


Popular Content

Showing content with the highest reputation on 01/11/22 in all areas

  1. Any c-tor could raise an exception if there's not enough memory. So IMHO scheme foo := TFoo.Create; try ... finally FreeAndNil(foo); end is OK. Otherwise you'll get "Variable might be uninit-ed" warning. Of course you can wrap this clause in external try-catch to handle an exception internally (default behavior is call Application.HandleException method) Regarding the ability to raise itself, yes, there's no helpers in the language. Sometimes I dream of something like Java's "throws" clause.
  2. Some bullet points: if Assigned(Obj) then Obj.Free is redundant, you can just call Obj.Free - Free is static and can be called on nil instance and also Free has nil check within before calling destructor constructors are allowed to raise exceptions destructors must never raise exceptions (without handling them within with try...except) destructors can be called on half constructed instance (if the constructor fails, destructor chain will be automatically called) and must be able to handle such scenarios without causing trouble - raising exceptions when constructor fails assignment to variable will never happen local object variables are never automatically initialized and they can contain random garbage object instance fields are always zero initialized when constructor chain is being called Because of the above correct construction pattern is var LA: TRaiseOnMinus; begin LA := TRaiseOnMinus.Create( -2 ); try //some code finally LA.Free; end; end; With multiple constructors there are multiple options, but I prefer using only single try...finally because destructors must not raise exceptions, single try finally is faster and cleaner var LA, LB: TRaiseOnMinus; begin LB := nil; LA := TRaiseOnMinus.Create( -2 ); try LB := TRaiseOnMinus.Create( -3 ); //some code finally LB.Free; LA.Free; end; end; Correct constructor and destructor for your class would be: constructor TRaiseOnMinus.Create( AParam : Integer ); begin inherited; if AParam < 0 then raise Exception.Create( 'Bum' ); FMyList := TStringList.Create; end; destructor TRaiseOnMinus.Destroy; begin FMyList.Free; inherited; end; Only if you need to do some additional work with FMyList in destructor, then you must check it for nil before using it. In such cases you can find call to Free within the same check, but not because it wouldn't work outside. destructor TRaiseOnMinus.Destroy; begin if Assigned(FMyList) then begin FMyList.DoSomethingImportant; FMyList.Free; end; inherited; end;
  3. I don't see the point of trying not to raise in a constructor as a design goal. Raise the exception at the point where you know it needs to be raised.
  4. What do you think about TFileStream.Create raising an exception if the file can be opened in the requested mode for whatever reason? I cannot see the problem with this, or indeed any constructor raising. If you are going to admit exceptions in your program at all, you must be resilient to them. Why is it any different to get the exception raised in a constructor than anywhere else.
  5. The problem with this pattern is that most methods of the class now has to perform some kind of validation before doing their job.
  6. The advantage of moving that teardown call to the subject's destructor is that you don't need to test Assigned. If it raises an exception then you are still hosed.
  7. This is pertinent to some of the discussion here: https://stackoverflow.com/a/8550628/505088
  8. I prefer NOT to raise exceptions in constructors - class nor otherwise. It makes securing the build up of the instance hierarchy too complicated. A lack of connectivity or functionality should only be addressed at the time of use, not at the time of instancing, considering their absence may be temporary. There is one case though - during testing, assertions may be used to check for stuff that SHOULD be in place.
  9. Although that might be the case, I recently turned to form a habit that avoids anything causing exceptions inside constructors. That may also lead to avoid giving parameters to constructors - at least when they are not being handled seamlessly during the lifetime of the instance. That allows to concentrate on the real work to be done instead of figuring out some tricky handling of edge cases. LA := TRaiseOnMinus.Create; try LA.Initialize(AInputA); //<== PossibleRaise LB := TRaiseOnMinus.Create; try LB.Initialize(AInputB); //<== Possible Raise { do the normal stuff with LA and LB } finally LB.Free; end; finally LA.Free; end;
  10. John Terwiske

    cppcon 2021

    There are now 48 talks on YouTube from this past October's conference. I was looking forward to seeing this one, and it didn't disappoint. The real takeaway for me was that the code we write is not necessarily what the cpu actually does. Something that I've know for a while, but this presentation really hammers it home from a knowledgeable expert. There's a lot here for we Delphi users, too.
  11. baoquan.zuo

    Special Offer for Documentation Insight

    Thanks for the kind words! I must admit, the current status of the product is far away from my expectation and I'm really sorry that the new version has not come out in such a long time. However, there is much in-progress working on the product. I hope good things will happen in the upcoming 2022.
  12. Uwe Raabe

    Special Offer for Documentation Insight

    As long as it keeps doing what it was made for even in newer Delphi versions I would not rate that negative. There is plenty of software just refusing to work anymore where I would love to see it in some maintenance mode.
  13. When has an abundance of visual noise been a problem before with Pascal, the most verbose of languages!!!
  14. Alexander Sviridenkov

    Right To Left Components

    FMX use different methods for text rendering on mobile and desktop platforms. On desktop platforms native OS methods are used (f.e. Direct2D text layout or CGContext) but on mobile platforms text is rendered as bitmap combination - each font symbol is stored in cache as bitmap. This leads to no RTL support, bad kerning, etc and also is slow., This is why I had to write native canvas support for these platforms.
×