Delphi: обработка того факта, что строки не являются объектами - PullRequest
6 голосов
/ 26 мая 2010

Я пытаюсь написать функцию, которая принимает любой TList и возвращает строковое представление всех элементов TList.

Я попробовал такую ​​функцию, как

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

Это отлично работает, за исключением того, что вы не можете передать ему TList<String>.

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

В Delphi строка не является объектом. Чтобы решить эту проблему, я написал вторую функцию:

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

Это единственное решение? Существуют ли другие способы рассматривать строку как «объектоподобную»?

В том же духе я также хотел написать функцию «равно», чтобы сравнить два списка TL. Я снова сталкиваюсь с той же проблемой

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

Есть ли способ написать эту функцию (возможно, с использованием обобщений?), Чтобы она также могла обрабатывать TList<String>? Есть ли какие-то другие приемы или «лучшие практики», о которых я должен знать при попытке создать код, который обрабатывает как строки, так и объекты? Или я просто создаю две версии каждой функции? Могут ли дженерики помочь?

Я из Java, но сейчас работаю в Delphi. Кажется, в последнее время они добавляют в Delphi много вещей из мира Java (или, возможно, из мира C #, который скопировал их из Java). Как добавление equals () и hashcode () к TObject, а также создание универсальной структуры Collections и т. Д. Мне интересно, насколько эти дополнения очень практичны, если вы не можете использовать с ними строки.

[править: кто-то упомянул TStringList. Я использовал это до сих пор, но я спрашиваю о TList. Я пытаюсь понять, является ли использование TList для всего (включая строки) более чистым способом.]

Ответы [ 3 ]

7 голосов
/ 26 мая 2010

Ваша проблема не в том, что string и TObject являются несовместимыми типами, (хотя они есть), а в том, что TList<x> и TList<y> являются несовместимыми типами, даже если сами x и y являются не. Причины сложны, но в основном это так.

Представьте, что ваша функция приняла TList<TObject>, а вы передали TList<TMyObject>, и она заработала. Но затем в вашей функции вы добавили TIncompatibleObject в список. Поскольку сигнатура функции знает только то, что она работает со списком объектов TObject, это работает, и вы неожиданно нарушили инвариант, и когда вы попытаетесь перечислить этот список и использовать внутри него экземпляры TMyObject, что-то может взорваться.

Если бы команда Delphi добавила поддержку ковариации и контравариантности для универсальных типов, то вы могли бы сделать что-то подобное безопасно, но, к сожалению, они еще не дошли до этого. Надеюсь, мы скоро это увидим.

Но, чтобы вернуться к исходному вопросу, если вы хотите сравнить список строк, нет необходимости использовать дженерики; В Delphi есть специальный класс list-of-strings, называемый TStringList, который находится в модуле Classes, который вы можете использовать. Он имеет множество встроенных функций для обработки строк, включая три способа объединения всех строк в одну строку: свойства Text, CommaText и DelimitedText.

1 голос
/ 25 марта 2011

Хотя это далеко не оптимально, вы можете создать класс оболочки строк, возможно, содержащий некоторые дополнительные полезные функции, которые работают со строками. Здесь - пример класса, который, возможно, следует улучшить, чтобы упростить управление памятью, например, используя эти методы .

Я только предлагаю решение вашей проблемы, я не согласен с тем, что согласованность ради согласованности сделает код лучше. Если вам это нужно, Delphi объект Паскаль может не быть языком выбора.

0 голосов
/ 31 мая 2010

Это не чище. Это хуже Принципиально ПЛОХАЯ идея использовать TList<String> вместо TStringList.

Нелегко говорить "я использую дженерики везде". На самом деле, если вы хотите быть последовательным, используйте их нигде. Избегайте их, как большинство разработчиков Delphi, избегайте их, как чумы.

Все «списки» строк в VCL имеют тип TStringList. В большинстве коллекций объектов в большинстве приложений Delphi вместо шаблонных типов используется TObjectList.

Не совсем понятно и непротиворечиво быть МЕНЬШЕ согласованным со всей платформой Delphi, выбирать какие-то странные вещи и стандартизировать их, когда это вы и только вы будете делать эту странную вещь.

На самом деле, я все еще не уверен, что дженерики безопасны для интенсивного использования.

Если вы начнете использовать TList, вы не сможете аккуратно скопировать его в Memo.Lines, который является TStringList, и вы создадите несовместимость типов, даром, плюс вы потеряете дополнительную функциональность в TStringList. , И вместо того, чтобы использовать TStringList.Text, вы должны придумать это для себя. Вы также теряете LoadFromFile, SaveToFile и многое другое. Массивы строк - вездесущая вещь в Delphi, и они почти всегда являются списком TStringList. TList<String> хромает.

...