Jump to content

A.M. Hoornweg

  • Content Count

  • Joined

  • Last visited

  • Days Won


A.M. Hoornweg last won the day on November 12

A.M. Hoornweg had the most liked content!

Community Reputation

81 Excellent

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. Fair enough. You're using the stringlist as an internally shared object, just for saving some time by not having to create/destroy one whenever you need one. You could take that concept one step further by creating a global stringlist pool (a singleton) from which you can request an available tStringlist whenever you need one. That pool could be shared among many objects and you could even make it threadsafe if you want. The problem of having local variables of managed data types such as strings is that Delphi needs to guarantee that no memory leaks occur. So there's always a hidden Try/Finally block in such methods that will "finalize" the managed variables and release any allocated heap space. That takes time to execute, even if there's no further "code" in the method.
  2. All the time. I am especially fond of classes that have only class methods. They basically act as namespaces.
  3. What exactly is a "local field" ? Do you mean a private field of a class (a member of an instantiated object, located on the heap) , or do you mean a local variable of a procedure or method (located on the stack) ?
  4. This makes the object unusable for multi-threading because it is unnecessarily stateful.
  5. Would that not potentially incur a cache miss, if the pointer points to a "remote" function?
  6. A.M. Hoornweg

    Ole DB (Ado) for MSSQL un-deprecated by Microsoft

    Could you please elaborate on that? Anything serious happening?
  7. A.M. Hoornweg

    Printing in a threaded program

    How do you detect if the printer is in use or not? You're accessing one stateful device that's effectively a singleton so the access has to be serialized. If you insist on using threads, you could write a dedicated printer thread.
  8. A.M. Hoornweg

    Initialization of returned managed types

    Thanks for mentioning this, downloading now...
  9. tDictionary<T> does manage the lifetime of refcounted objects (interfaces, strings, anonymous methods, ...). If it's in the dictionary, then that's proof that the object is still alive. Try achieving that with "tcomponent.tag!"... tObjectlist<T> can manage the lifetime of plain vanilla tObject and the user can specify whether he his wishes this behavior or not in the constructor. If yes, no dangling pointers, because the user is not supposed to free manually. Of course the user is not protected from doing silly stuff like still freeing the objects manually. That's life. Yes dictionaries add a few dozen KB to the executable. But hey, RTTI adds a megabyte or so of metadata and for many/most of us it's only dead weight. If there's one single place in the compiler chain where we should be given more control, it's there. Anyway, I myself have stopped using Tag for pointers to objects because dictionaries made my life much easier. I find myself often using strings as a key because I totally like it when the code tells what it's doing. Tag will only store a fixed pointer, but a dictionary will let me query if an object exists and where it is stored, without any ugly typecasting, in a compact and legible way. 🙂 procedure tform1.Button1click(sender:tobject); var callback:tReportShowEvent; begin if ReportDict.TryGet('CurrentReport',callback) then Callback(); end;
  10. "tag" can fit a simple pointer-sized reference, sure, but you still need to handle ownership of the object. Also, "tag" has no way of knowing if the object it points to is still valid, you may need to clear the tag if the object is freed. That means writing boilerplate code. TDictionary and tObjectdictionary are "better" because they can handle object ownership. TDictionary<T> can contain managed objects such as strings, interfaces and (I suspect) even anonymous methods. If tDictionary manages the lifetime of the objects, there can't possibly be an invalid association and it reduces boilerplate code.
  11. This is what I'm missing in the current version of the type library editor (see attachment): the possibility to use Pascal syntax instead of IDL Syntax. In Delphi 2007 it was still there!
  12. Does anybody know in which Delphi version the TLB editor ceased to support Delphi syntax?
  13. Safecall does the same as stdcall returning a hresult and letting no exceptions out. It saves a lot of boilerplate code.
  14. You said it is a COM server. In that case your method has to be declared "safecall". Function tmyclass.method1:Olevariant; Safecall; That basically does the same as returning the Olevariant as an OUT parameter but in the background it additionally returns an integer (hresult) which tells the caller if the call was successful or not. [Edit] I just see you use the type library editor. Since a couple of years Delphi's type library editor no longer works with Delphi syntax directly, unfortunately, but only with RIDL syntax which looks a bit like C. Here you can see that the function's result is a HResult and the Olevariant is an OUT parameter. You will also see that the automatically created Delphi interface has functions using the "safecall" calling convention. Older versions of Delphi had a type library editor that could work in Delphi syntax directly, I found that much more straightforward to use.
  15. Please don't misuse "tag" for pointers. I'd rather use a tDictionary<tcomponent, tSomethingelse> to store associations between components and objects. It's much more universal and transparent.