Delphi: handling the fact that strings are not objects

I am trying to write a function that accepts any TList and returns a string representation of all TList elements.

I tried such a function

function ListToString(list:TList<TObject>):String; 

This works fine except that you cannot pass a TList<String> .

 E2010 Incompatible types: 'TList<System.TObject>' and 'TList<System.string>' 

In Delphi, a string is not an object. To solve this problem, I wrote a second function:

 function StringListToString(list:TList<string>):String; 

Is this the only solution? Are there other ways to treat String as being more "object-like"?

In a similar vein, I also wanted to write a function called 'equals' to compare two TLists. Again I am facing the same problem

 function AreListsEqual(list1:TList<TObject>; list2:TList<TObject>):boolean; 

Is it possible to write this function (possibly using generics?) So that it can also handle TList<String> ? Are there any other tricks or “best practices” that I should be aware of when trying to create code that processes both strings and objects? Or am I just creating two versions of each function? Can generics help?

I am from the Java background, but now I work in Delphi. It seems they have been adding a lot of things to Delphi lately from the Java world (or maybe the C # world that copied them from Java). Like adding equals () and hashcode () to a TObject and creating a common collection structure, etc. I wonder how these add-ons are very practical if you cannot use Strings with them.

[edit: Someone mentioned TStringList. I have used this so far, but I am asking about TList. I am trying to work if using TList for everything (including Strings) is a cleaner way to go.]

+6
delphi delphi-2010
source share
3 answers

Your problem is not that string and TObject are incompatible types (although they are), that TList<x> and TList<y> are incompatible types, even if x and y themselves are not. The reasons why it is difficult, but basically, it happens as follows.

Imagine that your function accepted TList<TObject> , and you passed it to TList<TMyObject> , and it worked. But then in your function you added a TIncompatibleObject to the list. Since the function signature knows that it works with the TObjects list, it works, and suddenly you break an invariant, and when you try to list this list and use TMyObject instances inside, something might explode.

If the Delphi team added support for covariance and contravariance in generic types, you could do something similar safely, but, unfortunately, they have not reached it yet. I hope we will see it soon.

But to get back to the original question, if you want to compare a list of strings, there is no need to use generics; Delphi has a specific string list class called TStringList, which is located in the Classes module, which you can use. It has many built-in functions for processing strings, including three ways to combine all strings into one string: Text, CommaText, and DelimitedText.

+7
source share

Although this is far from optimal, you can create a string wrapper class, possibly containing some additional useful functions that work with strings. Here is an example class that needs to be improved to simplify memory management, for example using these methods .

I only propose a solution to your problem, I do not agree that consistency for consistency will make the code better. If you need it, Delphi cannot be the selected language.

+1
source share

This is not cleaner. This is worse. It is basically a BAD idea to use a TList<String> instead of a TStringList .

It's not cleaner to say that I use generics everywhere. In fact, if you want to be consistent, use them nowhere. Avoid them, as most delphi developers avoid them like a plague.

All "lists" of strings in VCL are of type TStringList. Most object collections in most delphi applications use TObjectList instead of template types.

This is no cleaner and more consistent LESS, compatible with the entire Delphi platform, and to select some strange thing, and standardize on it when it will be for you, and you alone, do this strange thing.

In fact, I'm still not sure that generics are safe to use.

If you start using TList, you cannot completely copy it to Memo.Lines, which is a TStringList, and you will create a type incompatibility, for nothing, in addition, you will lose additional functionality in TStringList, and instead of using TStringList.Text you must come up with it. You also lose LoadFromFile and SaveToFile and more. String arrays are the ubiquitous thing in Delphi, and they are almost always a TStringList. TList<String> is lame.

0
source share

All Articles