Jump to content

Stefan Glienke

Members
  • Content Count

    1449
  • Joined

  • Last visited

  • Days Won

    145

Everything posted by Stefan Glienke

  1. Stefan Glienke

    Guidance on FreeAndNil for Delphi noob

    The best practice is coding in a way that you don't need it
  2. Stefan Glienke

    pasfmt out now!

    It always is just a matter of taste - I don't particularly like the parameter and local variable prefixing so I mostly settled on the C# naming conventions for those - I did not want to go that far to name fields with a leading underscore like them though. Though this is not without disadvantages - I had cases where I had a count parameter and wanted to access the Count field but without qualifying with Self I accessed the parameter instead. (those are the days where I wished for case sensitivity) Because being open source means that everyone can go ahead and modify it to their liking, right?
  3. Stefan Glienke

    pasfmt out now!

    Looks great - as always: spring4d source for the real test and it seems to stumble at a few places where it then goes into "line breaks go to 11" mode - here for example: or
  4. Stefan Glienke

    Looking but not finding...

    That comment didn't age well I guess
  5. I bet the C++ code does not do the same as TIniFile in Delphi which calls WritePrivateProfileString for every entry.
  6. Without saying too much there is the possibility that this issue (https://embt.atlassian.net/servicedesk/customer/portal/1/RSS-2458) will be fixed in the next release.
  7. I am all for better optimization performed by the compiler but this particular case is not among them - if you write empty methods then use some static code analysis to let them be detected and remove them. Optimizing out empty methods (and here we are not talking about some regular methods but ctor and dtor!) is something that most compilers don't do for various reasons. Only when methods get inlined (which is not possible for virtual methods unless devirtualization is possible but that's an entirely different story) the compiler can detect that there actually is nothing to (and calling inherited is not nothing) and in fact the Delphi compiler does that - but ctor and dtor can not be inlined. The case you show here gets more interesting though if you remove all the empty ctors and dtors because then I still see a slight difference of 10-15%. The reason for that is TObject.InitInstance P.S. Just FYI if I run the benchmark without the empty ctor and dtor in Delphi 12 release config I get these numbers: BaseClass: 106,01 ms unneeded inheritance: 119,40 ms The same code compiled in Delphi 10.1 gives these numbers - so much about "there is no progress on optimization": BaseClass: 156,23 ms unneeded inheritance: 175,53 ms Although these particular differences are most likely because of the following two improvements I provided: Better TObject.InitInstance Better _FinalizeRecord
  8. Stefan Glienke

    DevEx VCL Components & VCL Styles??

    There seems to be an adapter to apply VCLStyles to DevExpress components: https://www.almdev.com/prods/stylecontrols/stylecontrols.html - I have no experience with this but at some point we will have to look into this as customers keep asking for Dark mode in our application 😎 🙈
  9. Stefan Glienke

    What new features would you like to see in Delphi 13?

    You are comparing Win32/Debug with Win64/Release *cough*
  10. Stefan Glienke

    What new features would you like to see in Delphi 13?

    Delphi developers.... one half still uses Delphi 7 and the other one does not even do 32-bit anymore
  11. Stefan Glienke

    CreateObservableList example in Spring4D

    All collections have events for getting notified of addition/removal via the OnChanged event - observable lists are something different. On those if the objects implement INotifyPropertyChanged they communicate to the list that a property has changed so the list then gets caChanged from those items.
  12. Most simple case to repro to compiler error: procedure X(i: Integer); begin end; procedure Y; begin var f: TFunc<Integer>; X(f); end;
  13. Stefan Glienke

    Get Index of enumeration in spring4D

    https://bitbucket.org/sglienke/spring4d/src/2.0.1/Source/Base/Collections/Spring.Collections.pas#lines-6391
  14. Stefan Glienke

    Get Index of enumeration in spring4D

    First of all, you can already achieve what you asked for in two different ways. (As I said, I will look into adding a similar method as .NET 9 did, but it's not as easy due to Delphi's limitations - it most likely will be a static method on TEnumerable and not on IEnumerable because it returns a differently typed IEnumerable, and that causes the Delphi compiler to complain with E2604.) Apart from the obvious use of a classic for-to loop if you already have an indexable collection such as IList where that new method IMHO would make no sense and just add overhead you can do this: var indexedColl := TEnumerable.Zip<Integer,TMyClass>(TEnumerable.Range(0, myColl.Count), myColl); for var curItem in indexedColl do Writeln('index: ', curItem.Value1, ' - item: ', curItem.Value2.ToString); If you want more control over index generation you can write this: var indexedColl := TEnumerable.Select<TMyClass, Tuple<Integer,TMyClass>>(myColl, function(const item: TMyClass; const index: Integer): Tuple<Integer,TMyClass> begin Result := Tuple<integer,TMyClass>.Create(index, item); end); for var curItem in indexedColl do Writeln('index: ', curItem.Value1, ' - item: ', curItem.Value2.ToString); If you then want to filter only certain indexes you just call Where on indexedColl: var oddIndexes := indexedColl.Where( function(const tuple: Tuple<Integer,TMyClass>): Boolean begin Result := Odd(tuple.Value1); end); for var curItem in oddIndexes do Writeln('index: ', curItem.Value1, ' - item: ', curItem.Value2.ToString);
  15. Stefan Glienke

    Get Index of enumeration in spring4D

    This would be a duplication of the already existing Where
  16. Stefan Glienke

    How to access/modify underlying records of IList<T>

    I have something like that in the works already. It does create a copy (records are value types, what else should it do?) - what you are proposing is dangerous and error-prone. That is not the case anymore in 2.0 - that interface has been removed from lists.
  17. Stefan Glienke

    Get Index of enumeration in spring4D

    No, but I see that .NET 9 added this. I might consider it.
  18. Stefan Glienke

    ISet<T> in spring4D

    FWIW if your type is an enum already it makes no sense to use ISet<T> because you can use the enum set. ISet<T> is for types that are no enums, such as string for example.
  19. Stefan Glienke

    Understanding DUnitX.Assert.WillRaise

    Passing parameters like that does not work in DUnitX - it silently ignores the string name for the exception class and then passes nil. Calling Assert.WillRaise with nil as exceptionClass succeeds when any exception was raised. @Vincent Parrett should be able to tell the best way to pass any parameters that cannot be easily converted from string.
  20. Stefan Glienke

    chatgpt can convert 32bit asm into 64bit

    Converting source code that won any challenge over 15 years ago is questionable regardless of correctness. Anyway, for this particular example, implementing a faster System.Move for Windows (other platforms use their libc memory) has been solved since Delphi 11.3. I sincerely challenge everyone to come up with a faster/better implementation.
  21. Stefan Glienke

    Strict type checking for tObject.

    It is pretty simple - imagine if the code below would work that way: procedure ReplacePet(var pet: TPet); begin pet.Free; pet := TCat.Create; end; procedure Main; var dog: TDog; begin ReplacePet(dog); dog.Bark; // meow?! end; FreeAndNil is special because it just destroys and assigns nil. But a var parameter does not give that guarantee.
  22. Stefan Glienke

    Double, default value

    Which - fun fact - does not happen on the method call (unless it's a virtual method) but when accessing any member inside of it. You could still have some method which does not access any member and it will not AV at all. We can argue all day about this - any runtime behavior one might slap onto it will not save the language from being inherently unsafe. It needs to be built into the language/compiler itself (Hi, Rust)
  23. Stefan Glienke

    Double, default value

    The main issue with memory safety in Delphi is not non-initialized local variables, which the compiler warns about, but use-after-free.
  24. Stefan Glienke

    Double, default value

    First, it's wrong to assume that all local variables reside on the stack, depending on optimization they might be in registers. Second, rep stosd is terribly slow for small sizes (see https://stackoverflow.com/a/33485055/587106 and also the discussions on this issue https://github.com/dotnet/runtime/issues/10744) Also, the Delphi compiler arranges managed local variables into one block that it zeroes (in many different and mostly terribly inefficient ways).
  25. Stefan Glienke

    Double, default value

    Why should the CPU waste time zeroing stuff that will be set shortly after anyway? Compilers are there to warn/error when any code path leads to a situation where a variable is not initialized.
×