-
var
Queue: TObjectQueue;
procedure InitQueue();
begin
Queue:= TObjectQueue.Create();
Queue.Push(TObject.Create());
Queue.Push(TButton.Create());
Queue.Push(TBitmap.Create());
end;
function GetNextNameOfObjectFromQueue(): String;
var
Value: TObject;
begin
Value:= Queue.Pop();
if Assigned(Value) then
begin
Result:= String(Value.ClassName);
end else
begin
Result:= '[ EMPTY ]';
end;
end;
procedure TForm1.Button8Click(Sender: TObject);
begin
Caption:= GetNextNameOfObjectFromQueue();
end;
По идее, если нажимать на кнопку, то в заголовке окна должны прописываться имена классов очереди.
После последнего элемента выкидывает такое: 'List index out of bounds (-1)'.
О чего так? Ведь по идее по окончании очереди Pop() должен вернуть nil.
-
> Ведь по идее по окончании очереди Pop() должен вернуть nil.
Может вернуть NIL, а может и исключение выбросить (что и делает). Все зависит от реализации.
-
> Ведь по идее по окончании очереди Pop() должен вернуть nil.
видимо нет. см. исходник.
-
Именно поэтому не стоит пользоваться подобными библиотеками и фреймворками - они могут выкинуть всё что угодно.
-
> они могут выкинуть всё что угодно.
хелп/исходники же есть...
function GetNextNameOfObjectFromQueue(): String;
begin
if Queue.Count > 0
then Result:= Queue.Pop().ClassName
else Result:= '[ EMPTY ]';
end;
-
> хелп/исходники же есть...
Хелп, созданный автоматической помощесоздалкой, который на 95% состоит из записей This is so-and-so method... Действительно серьёзное подспорье в использовании кода. Тем более, что так ничего и не понятно, почему очередь выкидывает исключение вместо возврата нуля...
-
хотя правильнее будет так:
function GetNextNameOfObjectFromQueue(): String;
begin
if Queue.Count = 0
then Result:= '[ EMPTY ]'
else
with Queue.Pop() do begin
Result:= ClassName;
Free;
end;
end;
-
> который на 95% состоит из записей This is so-and-so method...
ну, не знаю, у меня нормальный
TObjectQueue
Hierarchy Methods See also
TObjectQueue maintains a first-in first-out list of objects.
Unit
Contnrs
Description
Use a TObjectQueue to store and maintain a first-in first-out list of objects.
Removes and returns the object at the front of the queue.
Delphi syntax:
function Pop: TObject;
C++ syntax:
HIDESBASE System::TObject* __fastcall Pop(void);
Description
Call Pop to retrieve an object from the queue. Pop removes the next object from the queue (that is, the earliest object added), then returns a reference to the deleted object.
To access the queue without removing an object, call Peek.
-
> Dimka Maslov © (03.04.16 20:47) [5]
> почему очередь выкидывает исключение вместо возврата нуля
Потому что NIL может сидеть в очереди. И если вместо исключения выдать NIL, то будет непонятно - то ли очередь пуста, то ли в ней NIL сидел. А с исключением все однозначно.
-
> sniknik © (03.04.16 20:48) [6]
> хотя правильнее будет так:
> function GetNextNameOfObjectFromQueue(): String;
> begin
> if Queue.Count = 0
> then Result:= '[ EMPTY ]'
> else
> with Queue.Pop() do begin
> Result:= ClassName;
> Free;
А зачем вызывать Free() ведь Pop() удаляет объект из очереди?
-
> Юрий Зотов © (03.04.16 21:10) [8]
> > Dimka Maslov © (03.04.16 20:47) [5]
>
> > почему очередь выкидывает исключение вместо возврата нуля
>
> Потому что NIL может сидеть в очереди. И если вместо исключения
> выдать NIL, то будет непонятно - то ли очередь пуста, то
> ли в ней NIL сидел. А с исключением все однозначно.
Точно! Что-то этот момент упущен был извиду. :)
-
> А зачем вызывать Free() ведь Pop() удаляет объект из очереди?
>
>
>
Если объект далее нужен, то Free конечно не нужно вызывать. Pop() только удаляет из очереди его, сам объект нужно уничтожать как обычно.
-
Вообще про nil в очереди конечно такое возможно, но на практике маловероятно, ибо проще не класть nil в очередь, чем потом проверять.
-
>
> Потому что NIL может сидеть в очереди
Я бы ни за что не стал пихать nil в очередь. Лучше создать "пустой" объект, нежели потом AV отлавливать.
-
> DVM © (03.04.16 22:11) [11]
> Dimka Maslov © (03.04.16 22:18) [13]
NIL в очереди (да и вообще в любом списке объектов) может быть значимым для алгоритма. Хотя я бы тоже от такого алгоритма, скорее всего, постарался бы воздержаться, но задачи разные бывают и NIL в списке может оказаться вполне удачным решением.
-
> NIL в очереди (да и вообще в любом списке объектов) может
> быть значимым для алгоритма
var
NilObject: TObject;
initialization
NilObject := TObject.Create;
после чего сравниваем с этим объектом на предмет пустоты объекта и с nil на предмет окончания очереди. При этом более не нужна проверка на количество объектов.
-
Dimka Maslov © (04.04.16 08:18) [15]
Я не до конца понимаю, зачем гордиться костылями ?
-
> Игорь Шевченко © (04.04.16 10:39) [16]
А в чём собственно костыль?
-
> Dimka Malov © (04.04.16 13:29) [17]
1. Заменили одну проверку другой. Стало лучше? Нет, стало хуже. Потому что сама проверка как была, так и осталась, только во втором варианте еще и спецобъект надо создавать (который, насколько я понял Игоря, костыль и есть).
3. В проект приходит новый разработчик, которому об этом спецобъекте забыли сообщить (100%, что так и будет). Бедняга честно пишет правильный код и не может понять, что за чудеса происходят в программе.
-
> Юрий Зотов © (04.04.16 16:34) [18]
1. Мы получили указатель и сравниваем его с нулём, как признаком окончания списка или с пустым объектом, что означает, что никакие действия не нужны. При этом не надо ещё каждый раз проверять количество объектов очереди - вот лишняя и ненужная проверка. Более того, отсутствие в списке нулей избавляет от AV когда по недосмотру объект убежит туда, где его не будут проверять, либо сама проверка уже даст ошибку.
2. Сложно представить, что здеся было.
3. Правильный код - это тот, который правильно работает, а не который написан именно так, как сказано "в теории".