2013-04-12 2 views
1

Я создал следующий класс, после прочтения о значительном улучшении производительности TDictionary над TStringList:как вызвать унаследованный конструктор TObjectDictionary в Delphi

TAnsiStringList = class(TObjectDictionary<AnsiString,TObject>) 
    public 
     constructor Create(const OwnsObjects: Boolean = True); reintroduce; 
     destructor Destroy; override; 
     procedure Add(const AString: AnsiString); 
     procedure AddObject(const AString: AnsiString; AObject: TObject); 
    end; 

Я закодировал конструктор так:

{ TAnsiStringList } 

    constructor TAnsiStringList.Create(const OwnsObjects: Boolean = True); 
    begin 
     if OwnsObjects then 
     inherited Create([doOwnsKeys,doOwnsValues]) 
     else 
     inherited Create; 
    end; 

... ожидая, что этот конструктор TObjectDictionary будет называться:

constructor Create(Ownerships: TDictionaryOwnerships; ACapacity: Integer = 0); overload; 

... если указан параметр Ownerships. Если домовладений параметр не указан, я ожидал, что следующий унаследовали TDictionary конструктор будет называться:

constructor Create(ACapacity: Integer = 0); overload; 

код компилируется и работает, но когда я называю

inherited Create([doOwnsKeys,doOwnsValues]) I get the following error: 

Недопустимый класс типаж

Кто-нибудь видит, что я делаю неправильно, и есть ли способ сделать это?

ТИА

ответ

3

Проблема заключается в том, что вы просите контейнер позвонить Free на ключи, когда элементы будут удалены. Но ваши ключи не являются классами, и поэтому это неверный запрос. Это ловушка во время выполнения, а не времени компиляции, поскольку владение не определяется до времени выполнения.

Необходимо только doOwnsValues и должен удалить doOwnsKeys.

if OwnsObjects then 
    inherited Create([doOwnsValues]) 
else 
    inherited Create; 

Для чего это стоит, если вы пытаетесь цветовым AnsiString эквивалентно TStringList, то ваш подход является ошибочным. Строковый список - это упорядоченный контейнер, но словаря нет. Вы не сможете индексировать по целому числу, итерировать по порядку и так далее. Я также не понимаю, почему вы хотите заставить всех потребителей этого класса объявить объекты типа TObject. Вы должны оставить этот параметр бесплатным, чтобы потребитель указал. Это красота дженериков.

Возможно, вам не нужен заказный контейнер, и в этом случае вам нужен словарь. Но в этом случае вам просто не нужно создавать новый класс. Вы можете просто использовать TObjectDictionary как есть.

Если вы мертв набор на создание класса к югу, то я бы сделал это так:

type 
    TAnsiStringDict<T: class> = class(TObjectDictionary<AnsiString, T>) 

Это позволит потребителю класса решить, какой тип объектов они положили в словаре, и поддерживать безопасность типа времени компиляции.

Итак, если вы хотите, словарь списков ваш объявить переменную как это:

var 
    ListBoxDict: TAnsiStringDict<TListBox>; 
+0

Спасибо за быстрый ответ. Причина, по которой я использовал этот подход, - это просто улучшение производительности при выполнении поиска в больших списках. Я часто использовал строковый список как текстовую систему индексирования в списках объектов.Если мне не нужно искать строку или объект с помощью числового индекса, почему бы не лучше использовать TObjectDictionary, так как это намного быстрее при поиске? – DelphiCoder

+0

Вы можете просто использовать 'TObjectDictionary' как есть. Если вам нужна версия, которая явно заставляет ваш выбор владения и выбирает «AnsiString» для ключей, по крайней мере, оставить параметр типа параметризованным. Тогда вы можете иметь безопасность типа. Вы можете обнаружить, что производительность хуже с помощью AnsiString. Если вы не используете 'AnsiString' везде и не трогаете методы RTL/VCL, которые будут конвертироваться в UTF-16 и из него. –

+0

* Если мне не нужно искать строку или объект с помощью числового индекса * Это нормально. Это мой последний абзац. Но тогда ваше имя класса ошибочно. Каждый кодер Delphi, который читает 'TAnsiStringList', будет считать упорядоченный массив, подобный контейнеру. –

Смежные вопросы