Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2007.11.11;
Скачать: [xml.tar.bz2];

Вниз

Как убить объект из его же метода?   Найти похожие ветки 

 
Ega23 ©   (2007-10-12 13:17) [0]

Собственно, сабж.

Есть идея с PostMesage  WM_DESTROY, но возникает вопрос - а если это не "оеонный" класс?


 
Ins ©   (2007-10-12 13:27) [1]


> но возникает вопрос - а если это не "оеонный" класс?

Например так:
1. Посылаем сообщение (WM_USER + 1 хотя бы) PostThreadMessage своему потоку, передавая параметром (например, wParam) Self.
2. В обработчике Application.OnMessage если пришло сообщение WM_USER + 1 вызываем TObject(wParam).Free;

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


 
Ega23 ©   (2007-10-12 13:30) [2]

Интересный вариант.
А если Application нет?


 
Ins ©   (2007-10-12 13:32) [3]

Очень интересный вариант привел DRON здесь:

http://www.delphikingdom.com/asp/answer.asp?IDAnswer=40427


> А если Application нет?

А цикл выборки сообщений есть? Если есть, то внутри его то же самое.


 
Ins ©   (2007-10-12 13:35) [4]

И еще вариант. Заводим специальное message-only окошко, и посылаем PostMessage ообщения ему.


 
Ins ©   (2007-10-12 13:39) [5]

Даже название для класса такого окна вам придумал :) SuicideManagerWindow


 
Slym ©   (2007-10-12 13:41) [6]

Ega23 ©   (12.10.07 13:17)
DelayedFree?
procedure DelayedFree(obj:Pointer);
 function ThreadProc(Aobj: Pointer): Integer;stdcall;
 begin
   TObject(Aobj).Free;
 end;
var FHandle,FThreadID:THandle;
begin
 FHandle:=CreateThread(nil,0,@ThreadProc,Pointer(obj),CREATE_SUSPENDED,FThreadID) ;
 SetThreadPriority(FHandle, THREAD_PRIORITY_IDLE);
 ResumeThread(FHandle);
 CloseHandle(FHandle);
end;


 
Ega23 ©   (2007-10-12 13:42) [7]

Так, с мест сообщают, что Application не будет.


 
Сергей М. ©   (2007-10-12 13:43) [8]


> Ega23 ©   (12.10.07 13:42) [7]


Ну хотя бы один TWinControl-объект будет ?


 
Slym ©   (2007-10-12 13:43) [9]

можно через стандартный TThread и synhronized гасить объект в главном потоке


 
Ins ©   (2007-10-12 13:43) [10]


> Slym ©   (12.10.07 13:41) [6]

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


 
Ins ©   (2007-10-12 13:45) [11]


> Ega23 ©   (12.10.07 13:42) [7]

[4] не подходит? Централизованно и не нужен никакой Application.


 
Ega23 ©   (2007-10-12 13:45) [12]


> Ну хотя бы один TWinControl-объект будет ?


Похоже что нет, это сервис с пайпами


 
Игорь Шевченко ©   (2007-10-12 13:50) [13]

тебе чего надо-то ?


 
palva ©   (2007-10-12 13:51) [14]

А разве обычным образом объект не убивается? Следующая программа печатает один и тот же адрес. То есть второй раз объект создается на месте убиенного.

{$APPTYPE CONSOLE}
uses Classes;
type
 TMyStringList = class(TStringList)
 procedure Dest;
 end;

procedure TMyStringList.Dest;
begin
 Free;
end;

var
 sl: TMyStringList;
begin
 sl := TMyStringList.Create();
 WriteLn(Integer(sl));
 sl.Dest;
 sl := TMyStringList.Create();
 WriteLn(Integer(sl));
 sl.Dest;
end.


 
Ins ©   (2007-10-12 13:56) [15]


> Ega23 ©   (12.10.07 13:45) [12]

Если там нет ни цикла выборки сообщений, ни окна он создавать не может, то сделать так:
1. Просто заносим ссылку на объект в некий список
2. Где-нибудь потом (не в методе какого-либо класса) сканируем этот список и уничтожаем объекты.


 
Ins ©   (2007-10-12 13:57) [16]


> palva ©   (12.10.07 13:51) [14]

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


 
Игорь Шевченко ©   (2007-10-12 13:58) [17]


> Убивается, но делать это в методе своего же класса не рекомендуется,
>  так как код метода после этого продолжает выполняться и
> любое обращение к self скорее всего приведет к исключению.
>


????????????????????


 
Ins ©   (2007-10-12 14:00) [18]


> Игорь Шевченко ©   (12.10.07 13:58) [17]

Что вас удивляет? В своем же методе (сабж вроде как об этом) вызывать Free небезопасно. После этого вызова метод продолжает выполняться, но экземпляра, на который указывает self уже нет.


 
Сергей М. ©   (2007-10-12 14:03) [19]


> сервис с пайпами


Ничто не мешает сервису создавать и испольновать окна.


 
palva ©   (2007-10-12 14:06) [20]

> но экземпляра, на который указывает self уже нет.
Все это понятно. Но я не уловил, в чем заключается трудности выполнения метода несуществующего объекта, если этот метод не обращается к полям.


 
palva ©   (2007-10-12 14:09) [21]

palva ©   (12.10.07 14:06) [20]
С другой стороны непонятна логика. Если после уничтожения объекта методу нужно обращаться к полям объекта, то зачем тогда уничтожать объект.


 
Ins ©   (2007-10-12 14:09) [22]


> если этот метод не обращается к полям.

Это очень важное если. А если этот метод вызван из другого метода, который потом обращается? А если этот другойвызван из третьего? А если где-то потом еще вызывается виртуальный метод (он же тоже подразумевает обращение к self)? Лучше просто так не делать и тогда жить будет чуточку легче.


 
Ins ©   (2007-10-12 14:11) [23]


> С другой стороны непонятна логика. Если после уничтожения
> объекта методу нужно обращаться к полям объекта, то зачем
> тогда уничтожать объект.

Очень много случаев, когда люди вызывают Sender.Free из обработчика события. А потом удивляются AV или abstract error-у. А ведь нет ничего удивительного. Примеры были (правда на другом форуме), могу привести.


 
Kolan ©   (2007-10-12 14:27) [24]

> 2. Где-нибудь потом (не в методе какого-либо класса) сканируем
> этот список и уничтожаем объекты.

В потоке например, который будет этот список без конца сканить и мочить объекты&#133

Ega,
А может просто сделать интерфейс? Пусть он(объек) сам помрёт когда не нужен будет&#133


 
Игорь Шевченко ©   (2007-10-12 14:29) [25]

Ins ©   (12.10.07 14:00) [18]


> В своем же методе (сабж вроде как об этом) вызывать Free
> небезопасно. После этого вызова метод продолжает выполняться,
>  но экземпляра, на который указывает self уже нет.


???????????????????????????????????????????????????????????

procedure TCustomForm.CMRelease;
begin
 Free;
end;

Вроде безопасно...CMRelease - это факт, СВОЙ метод для объекта TCustomForm


 
Игорь Шевченко ©   (2007-10-12 14:30) [26]


> Это очень важное если. А если этот метод вызван из другого
> метода, который потом обращается? А если этот другойвызван
> из третьего? А если где-то потом еще вызывается виртуальный
> метод (он же тоже подразумевает обращение к self)? Лучше
> просто так не делать и тогда жить будет чуточку легче.


Совсем легко станет если учить матчасть. (Уж извини)


 
Ins ©   (2007-10-12 14:31) [27]


> В потоке например, который будет этот список без конца сканить
> и мочить объекты…

Не понимает народ.. На мультипроцессорной системе этот поток может выполняться одновременно с главным и замочить объект в то время, пока главный с ним работает. В этом случае нет принципиальной разницы с простым вызовом Free из своего же метода. Такой поток придется синхронизировать с главным. Чтобы главный в это время уже закончил работать с объектом. А раз так, то зачем еще один поток, сделаем в главном, только при завершении работы с объектом. Веди наверняка главный поток вертиться в каком-либо цикле, вот в конце цикла и анализировать список и убивать объекты. Вполне безопасно.


 
Ins ©   (2007-10-12 14:40) [28]


> Вроде безопасно...CMRelease - это факт, СВОЙ метод для объекта
> TCustomForm

Безопасно? Ну пошлите это сообщение (CM_RELEASE) через SendMessage или Perform где-то из глубины кода метода, который потом еще что-то делает с self-ом. Посмотрим :) Вот даже пример:

procedure TForm1.Button1Click(Sender: TObject);
begin
 Perform(CM_RELEASE,0,0);
 Caption:="123";
end;


Я не говорю, что так делать нельзя. Я говорю, что это небезопасно и рано или поздно свой эксепшн поймаешь.


 
Ins ©   (2007-10-12 14:46) [29]


> Вроде безопасно...

Только при соблюдении ряда условий, которые Borland сами для нас соблюли (см метод Release).


 
Leonid Troyanovsky ©   (2007-10-12 14:49) [30]


> Игорь Шевченко ©   (12.10.07 14:29) [25]

> Вроде безопасно...

Особенно забавно в главной форме:

procedure TForm1.Button1Click(Sender: TObject);
begin
 Release;
 ShowMessage("The end");
end;

т.е., приложение продолжит жить бесформенно.

--
Regards, LVT.


 
Игорь Шевченко ©   (2007-10-12 14:58) [31]

Ins ©   (12.10.07 14:40) [28]
Leonid Troyanovsky ©   (12.10.07 14:49) [30]

Если в коде написать:

Foo.Free
Foo.Bar := smth

И получится ошибка, вас это не удивит ? :)


 
palva ©   (2007-10-12 14:59) [32]

Вобщем я так и не понял вопроса. Как убить, если убивать нельзя.


 
Ins ©   (2007-10-12 15:03) [33]


> И получится ошибка, вас это не удивит ? :)

Не удивит. Меня удивляет лишь то, что вы тоже самое и предлагаете сделать, и говорите, что это вполне себе безопасно. :) Хотя, хозяин-барин, просто когда вы, или тот, кому вы посоветуете так сделать, не обговорив все "но", разобьет себе лоб - не удивляйтесь.


 
Ins ©   (2007-10-12 15:06) [34]


> Как убить, если убивать нельзя.

Можно, даже варианты предложены. :) В большинсвте своем они подобны методу Release - посылка асинхронного сообщения. Только разница в том кому посылать. Если самому себе (правда нужно чтобы объект был оконным), то нужно соблюсти правило "необращения к Self после Free".


 
palva ©   (2007-10-12 15:07) [35]

Ну а кто говорит, что это безопасно. Здесь лишь говорят, что никакой разницы в убивании объекта из метода или не из метода нет. Убить можно и так, и так, но только потом помнить, что объект убит и не пользоваться его полями.


 
Игорь Шевченко ©   (2007-10-12 15:10) [36]

Ins ©   (12.10.07 15:06) [34]

Я к тому, что твой и Леонида примеры по сути аналогичны моему с заведомым удалением объекта.
Но никто же при этом не утверждает, что вызов Free небезопасен, нес па ?


 
palva ©   (2007-10-12 15:12) [37]

> Можно, даже варианты предложены.
Ну это уже не из метода будет. Автор хочет из метода. И у него нет никаких препятствий (кроме заповеди "не убий") это сделать. Небезопасно - это возможно. Но настолько же небезопасно, как в основной программе уничтожить объект и сразу же им воспользоваться.


 
Leonid Troyanovsky ©   (2007-10-12 15:13) [38]


> Игорь Шевченко ©   (12.10.07 14:58) [31]

> И получится ошибка, вас это не удивит ? :)

А я и не делал ничего подобного Foo.Bar := smth.

Более того, в хелпе обещали, что Release сработает
после выхода из обработчика (какая самонадеянность)

--
Regards, LVT.


 
Ins ©   (2007-10-12 15:20) [39]


> palva ©   (12.10.07 15:12) [37]

Просто можно сделать безопасно. Сделав это не из метода своего класса. Иначе - небезопасно, так как метод продолжает выполняться с невалидным self. Повезет-неповезет, зависит от того, как это реализует программист. Задумается ли он о многих не очень очевидных вещах (в частности, что не только к полям нельзя обращаться, но и к виртуальным методам). И от того, откуда этот метод вызван. Если из другого метода, то теперь ответственность на том другом методе.


 
oxffff ©   (2007-10-12 15:26) [40]

Можно убивать по разному, главное чтобы убить. А как это без разницы.


 
Ins ©   (2007-10-12 15:31) [41]

Даже PostMessage самому себе (как сделано в Release) тоже не так чист как кажется с той точки зрения, что обработчик сообщения вызывается из другого метода (Dispatch что-ли), а тот - из WndProc. Если ничего не путаю, точнее нужно глянуть исходники. Так вот, вызывая Free в обработчике CM_Release - мы полностью доверяем Борланду, что после вызова этого обработчика и возврата в Dispatch и WndProc не будет никакого обращения к Self. Так что делая так, скрестите пальцы и молитесь-молитесь... :) Хотя на самом деле не будет, Борланд об этом позаботился.


 
oxffff ©   (2007-10-12 15:32) [42]


> Ins ©   (12.10.07 15:20) [39]
>
> > palva ©   (12.10.07 15:12) [37]
>
> Просто можно сделать безопасно. Сделав это не из метода
> своего класса. Иначе - небезопасно, так как метод продолжает
> выполняться с невалидным self. Повезет-неповезет, зависит
> от того, как это реализует программист. Задумается ли он
> о многих не очень очевидных вещах (в частности, что не только
> к полям нельзя обращаться, но и к виртуальным методам).
> И от того, откуда этот метод вызван. Если из другого метода,
>  то теперь ответственность на том другом методе.


Если слегка подумать и подмутить, то можно сделать так, что после вызова Free можно у объекта вызывать методы, в том числе и виртуальные и обращаться к полям. :)
Все в твоих руках. Это так к сведению


 
Игорь Шевченко ©   (2007-10-12 15:35) [43]

на С# надо писать. Там мусор собирается. Сам.


 
Ins ©   (2007-10-12 15:37) [44]


> oxffff ©   (12.10.07 15:32) [42]

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


 
Игорь Шевченко ©   (2007-10-12 15:38) [45]

Ins ©   (12.10.07 15:37) [44]

Практика показывает, что наступают абсолютно на все грабли, на которые только можно наступить, и по несколько раз :)


 
oxffff ©   (2007-10-12 15:38) [46]


> Игорь Шевченко ©   (12.10.07 15:35) [43]
> на С# надо писать. Там мусор собирается. Сам.


Неа. Tobject надо знать. ;)
Перекрываем FreeInstance оставляем Cleanup.
И добавляет добавление в очередь на удаление из кучи, которую (очередь) можно проверять в отдельном потоке. Вот вам почти .NET.


 
Ins ©   (2007-10-12 15:39) [47]


> Ins ©   (12.10.07 15:37) [44]

А все из-за того, что обращение к self иногда идет неявно. Как с теми же виртуальными методами. Потом очень долго ищут ошибку.


 
oxffff ©   (2007-10-12 15:40) [48]


> oxffff ©   (12.10.07 15:38) [46]
>
> > Игорь Шевченко ©   (12.10.07 15:35) [43]
> > на С# надо писать. Там мусор собирается. Сам.
>
>
> Неа. Tobject надо знать. ;)
> Перекрываем FreeInstance оставляем Cleanup.
> И добавляет добавление в очередь на удаление из кучи, которую
> (очередь) можно проверять в отдельном потоке. Вот вам почти
> .NET.


Каким образом до очередной сборки мусора, Обращение к объекту или виртуальному методу во всяком случае не вызовет ошибку.


 
Игорь Шевченко ©   (2007-10-12 15:42) [49]

oxffff ©   (12.10.07 15:38) [46]

При всем уважении не могу согласиться :) Чем-то мне это напоминает реактор на субтепловых нейтронах и шины из полиаминного нестирающегося волокна.


 
oxffff ©   (2007-10-12 15:43) [50]

procedure TXObject.FreeInstance;
begin
 CleanupInstance;
PendingQueue.insert(self);
end;

procedure KillAllPendingObject;
begin
//проходим по очереди и вызывает Free для каждого элемента
end;


 
oxffff ©   (2007-10-12 15:46) [51]


> Игорь Шевченко ©   (12.10.07 15:42) [49]
> oxffff ©   (12.10.07 15:38) [46]
>
> При всем уважении не могу согласиться :) Чем-то мне это
> напоминает реактор на субтепловых нейтронах и шины из полиаминного
> нестирающегося волокна.


Вы знаете делать можно по разному. Главное чтобы работало.
За это я очень ценю гибкость Delphi.


 
oxffff ©   (2007-10-12 15:47) [52]


> procedure KillAllPendingObject;
> begin
> //проходим по очереди и вызывает Free для каждого элемента
> end;


Freemem естественно.


 
Сергей М. ©   (2007-10-12 15:49) [53]


> я очень ценю гибкость Delphi


Оную твою "любовь" и видно по твоим постам)


 
oxffff ©   (2007-10-12 15:52) [54]


> Сергей М. ©   (12.10.07 15:49) [53]
>
> > я очень ценю гибкость Delphi
>
>
> Оную твою "любовь" и видно по твоим постам)


День добрый Сергей М. :)


 
palva ©   (2007-10-12 16:23) [55]


> > я очень ценю гибкость Delphi
> Оную твою "любовь" и видно по твоим постам)

А он и не говорил, что любит. Говорил что ценит.
Ценить - это любить за деньги.


 
Leonid Troyanovsky ©   (2007-10-12 18:18) [56]


> Игорь Шевченко ©   (12.10.07 15:10) [36]


type
 EFreeObject = class(EAbort)
   private
     FObject : TObject;
   public
     property AObject: TObject read FObject;
     constructor CreateFO(AObject: TObject); virtual;
     destructor Destroy; override;
 end;

constructor EFreeObject.CreateFO(AObject: TObject);
begin
 inherited CreateFmt("Object %p, classname %s", [Pointer(AObject), AObject.ClassName]);
 FObject := AObject;
end;

destructor EFreeObject.Destroy;
begin
 if (FObject = Application) or
    (FObject = Application.MainForm) then
   Application.Terminate
 else
   FObject.Free;
 inherited;
end;

procedure FreeObject(AObject: TObject);
begin
 raise EFreeObject.CreateFO(AObject);
end;

Тестировалось по-пятничному :)

--
Regards, LVT.


 
oxffff ©   (2007-10-12 22:32) [57]


> Leonid Troyanovsky ©   (12.10.07 18:18) [56]


> Тестировалось по-пятничному :)


Я если исключение не дойдет до  Application.HandleException(Self)?

Извольте получить AV

procedure TForm1.Button1Click(Sender: TObject);
var A:Tobject;
begin
a:=Tobject.Create;
try
FreeObject(a);
except
end;
showmessage(a.ClassName);
end;

Пример упрощен.
Так что и в этом случае гарантии попаданения в почти в "top caller", т.е MainWndProc нет.


 
Leonid Troyanovsky ©   (2007-10-13 10:17) [58]


> oxffff ©   (12.10.07 22:32) [57]

> Так что и в этом случае гарантии попаданения в почти в "top
> caller",

Ну, я надеюсь, что уважаемый Ega23 не будет в локальных
обработчиках гасить EAbort.

А чтобы не вводить никого в заблуждение откажемся от FreeObject
и будем звать непоср-но raise EFreeObject.CreateFO(AObject).

--
Regards, LVT.


 
Сусл ©   (2007-10-13 11:44) [59]

а в чем проблема убить?
берешь и убиваешь.

tobject.free посмотри


 
Leonid Troyanovsky ©   (2007-10-13 12:31) [60]


> Сусл ©   (13.10.07 11:44) [59]

> tobject.free посмотри

Посмотри остальные 57 сообщений.

--
Regards, LVT.


 
Leonid Troyanovsky ©   (2007-10-15 14:06) [61]


> Leonid Troyanovsky ©   (13.10.07 10:17) [58]

> А чтобы не вводить никого в заблуждение откажемся от FreeObject
> и будем звать непоср-но raise EFreeObject.CreateFO(AObject).

Продвигаемся еще дальше и откажемся от автоматического
разрушения объекта после обработки исключения.

Т.е., если некий объект не может больше работать, то он
должен возбудить исключение (необязательно класса EAbort),
для информирования об этом обстоятельсве того, кто вызвал
метод этого объекта, а уж в обработчике исключений этого
уровня принимать решение о дальнейшей судьбе объекта.

В любом случае, удерживаемая на этом уровне ссылка
на объект может быть обнулена вовремя.

--
Regards, LVT.


 
Игорь Шевченко ©   (2007-10-15 15:29) [62]

Leonid Troyanovsky ©   (15.10.07 14:06) [61]


> Т.е., если некий объект не может больше работать, то он
>
> должен возбудить исключение (необязательно класса EAbort),
>
> для информирования об этом обстоятельсве того, кто вызвал
>
> метод этого объекта, а уж в обработчике исключений этого
>
> уровня принимать решение о дальнейшей судьбе объекта.


Это я понимаю, выпрямители там, тумбы разные, это нам товарищ ВрИО довольно хорошо объяснил. Но вот один момент до конца не понятен - а нафига, собственно, нужны действия в отквоченном тексте ?


 
Leonid Troyanovsky ©   (2007-10-15 15:40) [63]


> Игорь Шевченко ©   (15.10.07 15:29) [62]

> а нафига, собственно, нужны действия в отквоченном тексте ?

Как мне представляется, это и есть ответ на вопрос из subject.

Т.е. (безопасно) уничтожить объект из его же метода нельзя.
Если желание, все же, не проходит, то действовать надо
в направлении [61].

--
Regards, LVT.


 
Игорь Шевченко ©   (2007-10-15 15:46) [64]

Leonid Troyanovsky ©   (15.10.07 15:40) [63]


> Т.е. (безопасно) уничтожить объект из его же метода нельзя.
>
> Если желание, все же, не проходит, то действовать надо
> в направлении [61].


Можно уничтожить. Если потом не обращаться к уничтоженному объекту :)
Отсюда, собственно и вопрос [62]


 
Ins ©   (2007-10-15 15:49) [65]


> Игорь Шевченко ©   (15.10.07 15:46) [64]

Мне тут недавно Юрий Зотов объяснял, что переходить дорогу не на переходе тоже можно. И курить на бочке с порохом тоже ;-) По-моему случай из той же оперы...


 
Leonid Troyanovsky ©   (2007-10-15 15:51) [66]


> Игорь Шевченко ©   (15.10.07 15:46) [64]

> Можно уничтожить. Если потом не обращаться к уничтоженному
> объекту :)

Мне не нравится "если". Умерла - так умерла.

Если добавить, например, к Release честное описание всех
условий (ограничений) ее применения, то применять ее не будут.
Хотя, и сама нужда в примение подобных вещей подозрительна :)

--
Regards, LVT.


 
Игорь Шевченко ©   (2007-10-15 15:59) [67]

Leonid Troyanovsky ©   (15.10.07 15:51) [66]

Если (уж извини!) ты в методе другого объекта обратишься к уничтоженному, то получишь тоже массу неприятных эффектов :)
Не следует ли из этого, что уничтожение объектов надо запретить вообще ?

Или я чего-то здорово не понимаю ? :)


 
Leonid Troyanovsky ©   (2007-10-15 16:12) [68]


> Игорь Шевченко ©   (15.10.07 15:59) [67]

> Или я чего-то здорово не понимаю ? :)

Ты снова подозреваешь меня в:
foo.Free;
foo.Smthng; :)

А я про неявное уничтожение.
Т.е., мы делаем:
foo.Smthng;
foo.Smthng2; // а в предыдущем вызове произошел суицид

Кроме того, мне не нравится, что после вызова "терминатора"
может происходить еще что-то неочевидное.

--
Regards, LVT.


 
Игорь Шевченко ©   (2007-10-15 16:27) [69]

Leonid Troyanovsky ©   (15.10.07 16:12) [68]


> Кроме того, мне не нравится, что после вызова "терминатора"
> может происходить еще что-то неочевидное.


Например, что ?


> А я про неявное уничтожение.
> Т.е., мы делаем:
> foo.Smthng;
> foo.Smthng2; // а в предыдущем вызове произошел суицид


Я с чем могу согласиться - что суицид объекта не самый ясный из примеров кода сам по себе. Читаешь код, видишь суицид, впадаешь в краткий ступор. С этим согласен и не спорю, лучше объект убивать принудительно извне - по крайней мере, читабельно.

Но городить дополнительный огород, чтобы все-таки разрешать суицид, и,  как следствие, неочевидный код - тут я впаду в еще больший ступор.
Так как я считаю, чем меньше ступора, тем лучше, то и задал вопрос [62] - а нафига ? :)


 
Суслик   (2007-10-15 17:07) [70]


>  [60] Leonid Troyanovsky ©   (13.10.07 12:31)
> > Сусл ©   (13.10.07 11:44) [59]
> > tobject.free посмотри
> Посмотри остальные 57 сообщений.


Осилил, ух...
Ну что сказать - разговор очень ни о чем, ибо знать надо контекст задачи лучше, чем это раскрыто в тексте топика.

Убиение себя - вещь неординарная. У меня в моем OPF фреймворке есть несколько таких моментов. Но каждый из них продокументирован жесточайщим образом с акцентами на тонкостях жизни после смерти.

Посему мое имхо - убивать себя объекту плохо, но если нужно, то почему нет? Free для этого вполне подходит.

ЗЫ Перечитал - ни о чем написал. Ну так и топик вобщем-то не особо информативен :)


 
Leonid Troyanovsky ©   (2007-10-15 17:49) [71]


> Игорь Шевченко ©   (15.10.07 16:27) [69]

> > Кроме того, мне не нравится, что после вызова "терминатора"
> > может происходить еще что-то неочевидное.

> Например, что ?

Например, если после вызова Free произойдет _неявный_
вызов еще чего-либо и в, конечном счете, к обращению
к уже несуществующему объекту.
Ну, не можем мы гарантировать, что вызов Free - последнее,
что выполняется в методе. Например, Release & ProcessMessages.

> Но городить дополнительный огород, чтобы все-таки разрешать
> суицид, и,  как следствие, неочевидный код - тут я впаду
> в еще больший ступор.

А я его и не разрешал, более того, никак не оправдывал.
Все, что я предложил в [61] - достаточно академично:

try
 foo.smthng; // при вызове метода объект может стать негоден к жизни
except
 on E: EFreeObject do
   begin
      foo.Free;
      raise; // дальнейшее выполнение кода с foo не имеет смысла
   end;
end;

Или освобождать foo в секции finally.
Вот, собс-но.

--
Regards, LVT.


 
Leonid Troyanovsky ©   (2007-10-15 18:03) [72]


> Суслик   (15.10.07 17:07) [70]

> Убиение себя - вещь неординарная. У меня в моем OPF фреймворке
> есть несколько таких моментов. Но каждый из них продокументирован
> жесточайщим образом с акцентами на тонкостях жизни после
> смерти.

Ну, а стоит ли делать столько оговорок, типа: после этого
вызова нельзя делать то-то и то-то, а это предварять этим.

Нам должно быть достаточно знать, что конструктор создает,
а Destroy - убивает, никакие компромиссы вроде функций,
возвращающих объект или методов-убийц нам не нужны.

А если при выполнении метода что-то пошло не так, то
исключение - вполне достойный способ известить об этом.

> ЗЫ Перечитал - ни о чем написал. Ну так и топик вобщем-то
> не особо информативен :)

Может и так.
Однако, мне удалось, надеюсь, избавиться от некоторых
заблуждений на эту тему.

--
Regards, LVT.


 
Palladin ©   (2007-10-15 18:07) [73]

ну, млин, из-за такой ерунды такую страшную дилему развели... реально, ИМХО, если вдруг объекту требуется самое себя уничтожить, то это уже ошибка проектирования...


 
Leonid Troyanovsky ©   (2007-10-15 18:23) [74]


> Palladin ©   (15.10.07 18:07) [73]

> .. реально, ИМХО, если вдруг объекту требуется самое себя
> уничтожить, то это уже ошибка проектирования...

Уже два ИМХО :)
Но, к сожалению (?), такие вещи голосованием не решают.

А самые длиные топики растут из ерунды, вроде
PChar & String, global variable - MD, формы в dll & etc :)

--
Regards, LVT.


 
oxffff ©   (2007-10-15 19:16) [75]


> Palladin ©   (15.10.07 18:07) [73]
> ну, млин, из-за такой ерунды такую страшную дилему развели.
> .. реально, ИМХО, если вдруг объекту требуется самое себя
> уничтожить, то это уже ошибка проектирования...


Странно, вообще все объекты себя сами убивают. См. destroy

Речь видимо шла об управлением временем жизни объекта?


 
Ins ©   (2007-10-15 19:19) [76]


> Например, Release & ProcessMessages.

Вот менее очевидный пример:

unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls;

type
 TForm1 = class(TForm)
   Button1: TButton;
   procedure Button1Click(Sender: TObject);
 private
   { Private declarations }
 protected
   procedure WndProc(var Message: TMessage); override;
   procedure WtiteToLog(Message: TMessage); virtual;
 public
   { Public declarations }
 end;

var
 Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
 Release;
end;

procedure TForm1.WndProc(var Message: TMessage);
begin
 inherited;
 WtiteToLog(Message);
end;

procedure TForm1.WtiteToLog(Message: TMessage);
begin
 // Do something
end;

end.


 
Leonid Troyanovsky ©   (2007-10-15 19:21) [77]


> oxffff ©   (15.10.07 19:16) [75]

> Речь видимо шла об управлением временем жизни объекта?

Видимо, речь шла о том, что видимо.
Убиение объекта из его же метода, см. сабж.

Вот, поэтому, IMHO, и обсуждения простых вещей столь длительны.
Потому, как каждый позволяет себе вольность восприятия темы
и ее предыдущих обсуждений.

--
Regards, LVT.


 
oxffff ©   (2007-10-15 19:28) [78]


> Видимо, речь шла о том, что видимо.
> Убиение объекта из его же метода, см. сабж.


Тогда каждый объект убивает себя сам.
Destroy, FreeInstance чьи методы? :)


 
oxffff ©   (2007-10-15 19:29) [79]


> Leonid Troyanovsky ©   (15.10.07 19:21) [77]


Возможно ли с вами как то связаться?


 
Leonid Troyanovsky ©   (2007-10-15 19:31) [80]


> Ins ©   (15.10.07 19:19) [76]

> Вот менее очевидный пример:

Эх, жаль, что он не более очевиден :)

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

--
Regards, LVT.


 
Leonid Troyanovsky ©   (2007-10-15 19:36) [81]


> oxffff ©   (15.10.07 19:28) [78]

> Тогда каждый объект убивает себя сам.
> Destroy, FreeInstance чьи методы? :)

Наши методы.

А речь-то была о не наших.
Т.е., о том, чтоб не рядили методы в белые одежды деструктора, f.e.
Тем более, что они могут сработать через раз.

--
Regards, LVT.


 
oxffff ©   (2007-10-15 19:39) [82]


> Leonid Troyanovsky ©   (15.10.07 19:36) [81]


Да я то понял, что вся наша дискуссия как всегда ни к чему не привела.
Точнее привела конечно же.
К тому, что в .NET таких вопросов в managed коде нет.


 
Leonid Troyanovsky ©   (2007-10-15 20:12) [83]


> oxffff ©   (15.10.07 19:29) [79]

lv.t[&]rambler.ru

--
Regards, LVT.


 
Leonid Troyanovsky ©   (2007-10-15 20:14) [84]


> oxffff ©   (15.10.07 19:39) [82]

> Да я то понял, что вся наша дискуссия как всегда ни к чему
> не привела.

Меня привела ;)

--
Regards, LVT.


 
oxffff ©   (2007-10-15 20:37) [85]


> Leonid Troyanovsky ©   (15.10.07 20:12) [83]


Да я собственно хотел бы знать ваше мнение насчет Yield.
А пока дождался вашего ответа создал тему.
Был бы рад услышать аргументированное мнение мастеров.

Прошу вас сюда
http://delphimaster.net/view/15-1192464844/
Заранее благодарен


 
Leonid Troyanovsky ©   (2007-10-15 21:17) [86]


> oxffff ©   (15.10.07 20:37) [85]

> Прошу вас сюда
> http://delphimaster.net/view/15-1192464844/

Честно говоря, мне там нечего сказать, бо, непонятно.
Наверное, устарел :)

Хотя, конечно, я с детства не любил ассемблер,
я с детства уважал фортран.
Sorry.

--
Regards, LVT.


 
Ins ©   (2007-10-15 21:27) [87]


> Меня привела ;)

Так может поделитесь! :)


 
Leonid Troyanovsky ©   (2007-10-15 21:43) [88]


> Ins ©   (15.10.07 21:27) [87]

> Так может поделитесь! :)

Да я, вообще-то, не скрывал :)

К [61] я ж не сразу пришел, была и некая эволюция,
т.е., ступень за ступенью.

Если добавить, скажем, нулевую ступень
http://groups.google.com/group/fido7.ru.delphi/msg/68eb8ca030e0bdce?dmode=source&output=gplain
(KOI8-R) {блин, как неудобно стало, как и в msdn.microsoft.com}
то все встанет на свои места, т.е. надо делать не как "лучше",
а как положено, т.е., через возбуждение исключения.

Ну, а неспешность подобного вывода смело спишу на
не особую актуальность подобных задач :)

--
Regards, LVT.


 
Игорь Шевченко ©   (2007-10-16 09:49) [89]

Leonid Troyanovsky ©   (15.10.07 17:49) [71]


> Например, если после вызова Free произойдет _неявный_
> вызов еще чего-либо и в, конечном счете, к обращению
> к уже несуществующему объекту.
> Ну, не можем мы гарантировать, что вызов Free - последнее,
>
> что выполняется в методе. Например, Release & ProcessMessages.
>


Все равно не согласен с необходимостью огорода :) Вот честно, положа руку на сердце, скажу - пользуюсь Release в ряде случаев, но редко, не возникает у меня необходимости убивать самое себя. Раз что-то используется крайне редко, для меня очевидно, что решение не типовое, и лучше (и понятней) будет, если перепроектировав я найду подходящее типовое решение. В последние несколько лет я стал истинным адептом понятного кода :)


 
Суслик   (2007-10-16 10:47) [90]


>  В последние несколько лет я стал истинным адептом понятного
> кода :)

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


 
homm ©   (2007-10-16 11:13) [91]

> [28] Ins ©   (12.10.07 14:40)
> Безопасно? Ну пошлите это сообщение (CM_RELEASE) через SendMessage
> или Perform где-то из глубины кода метода, который потом
> еще что-то делает с self-ом.

Я тебя не могу понять, что за ветряные мельницы? Как будто после вызова Free  не из метода можно обращатся к полям, или работать из другово потока? Если ты вызвал метод, который уничтожит объект, ты и не работай с ним больше, а если нужно работать, то и не вызывай.


 
homm ©   (2007-10-16 11:15) [92]

… или уж тогда  доказывай, что вызывать Free не безопасно нигде, и этого нельзя делать.


 
Ins ©   (2007-10-16 11:19) [93]


> Я тебя не могу понять, что за ветряные мельницы?

А это и не требуется, кому надо - тот смог. Даже Borland это поняли, вот и ввели метод Release, правда, как справедливо заметил г-н Leonid Troyanovsky ©, не обговорив всех НО его применения.

> Если ты вызвал метод, который уничтожит объект, ты и не
> работай с ним больше, а если нужно работать, то и не вызывай.

Есть очень коварное место (обработчик событий) в котором может понадобится уничтожить Sender, но так как класс может быть сторонний, ты не контролируешь то, что будет после этого уничтожения вызвано.


 
homm ©   (2007-10-16 11:23) [94]

> [93] Ins ©   (16.10.07 11:19)
> Есть очень коварное место (обработчик событий) в котором
> может понадобится уничтожить Sender, но так как класс может
> быть сторонний, ты не контролируешь то, что будет после
> этого уничтожения вызвано.

Ты имеешь ввиду ?
TForm1.Button1Click(Sender);
begin
 Sender.Free;
end


 
Ins ©   (2007-10-16 11:30) [95]

Я не имею в виду ничего конкретного. Я имею в виду целый класс задач, где это может быть востребовано.


 
Игорь Шевченко ©   (2007-10-16 11:44) [96]


> поделись понятным кодом


printf("Hello, world\n");


 
Сусл ©   (2007-10-16 12:09) [97]


>  [96] Игорь Шевченко ©   (16.10.07 11:44)
> > поделись понятным кодом
> printf("Hello, world\n");


а без сарказму? :) Действительно хочется поучится написанию понятного кода (к Макконелу не отсылай, ибо то книга, а тут жизнь).

или это намек, что код будет на си?


 
Leonid Troyanovsky ©   (2007-10-16 12:43) [98]


> Игорь Шевченко ©   (16.10.07 09:49) [89]

> очевидно, что решение не типовое, и лучше (и понятней) будет,
>  если перепроектировав я найду подходящее типовое решение

Надеюсь, что когда ты будешь нечто подобное перепроектировать,
то попробуешь и обсуждаемый подход instead Release :)

А вот, кста, у уважаемого Ega23 и форм никаких не было,
ему б в самый раз он пригодился.

--
Regards, LVT.


 
Игорь Шевченко ©   (2007-10-16 13:54) [99]

Leonid Troyanovsky ©   (16.10.07 12:43) [98]

Уважаемый Ega23 так и не озвучил, зачем ему сабж понадобился. Или я что-то пропустил ? :)


> Надеюсь, что когда ты будешь нечто подобное перепроектировать,
>
> то попробуешь и обсуждаемый подход instead Release :)


Я органически не могу писать лишний код :) До сих пор обходился Release для форм (в трех местах из проекта на миллион строк - специально только что поискал), а объекты не уничтожал внутри их методов.


 
Игорь Шевченко ©   (2007-10-16 13:56) [100]

Сусл ©   (16.10.07 12:09) [97]

А какой тебе код привести ? Просто не понимаю. Выкладывать куски коммерческих проектов не хочется, старый мой код можно по тырнету найти, с тех пор форма написания слегка изменилась (надеюсь, в лучшую сторону).


 
Сусл ©   (2007-10-16 14:02) [101]


>  [100] Игорь Шевченко ©   (16.10.07 13:56)
> Сусл ©   (16.10.07 12:09) [97]
>
> А какой тебе код привести ? Просто не понимаю. Выкладывать
> куски коммерческих проектов не хочется, старый мой код можно
> по тырнету найти, с тех пор форма написания слегка изменилась
> (надеюсь, в лучшую сторону).

куски кода, которые бы демонстрирвоали, что такое понятный код. я нисколько не сомневаюсь в твоих способностях писать понятный код. но, согласись, что это толко слухи - вот ты говоришь, что пишешь понятный код, Юра говорит. а код то понятный где? может это самообман? так лучше разоблачить этот самообман как можно раньше. А? если не самообман и понятный код есть, то многие тебе спасибо скажут.


 
Игорь Шевченко ©   (2007-10-16 14:24) [102]


> вот ты говоришь, что пишешь понятный код, Юра говорит. а
> код то понятный где?


В проектах вестимо - где ж ему еще быть. Выкладывать сюда куски проектов ? Так места мало...Hello, world тебя не устраивает.

Давай такой кусок выложу:

unit MemberQBEResultView;

interface
uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, DataViewTemplate, ActnList, Menus, DB, Grids, DBGridEh, ExtCtrls,
 StdCtrls;

type
 TfMemberQBEResultView = class(TfDataViewTemplate)
   actDetailView: TAction;
   Detailview1: TMenuItem;
   N1: TMenuItem;
   procedure FormCreate(Sender: TObject);
   procedure FormDestroy(Sender: TObject);
   procedure actDetailViewExecute(Sender: TObject);
   procedure GridDblClick(Sender: TObject);
   function  GetRecordCount: Integer;
 private
   SRecordCountCaption: string;
 protected
   procedure LocalizeInterface; override;
   property RecordCount: Integer read GetRecordCount;
 public
   procedure UpdateRecordCount;
 end;

var
 fMemberQBEResultView: TfMemberQBEResultView;

implementation
uses
 ArgoConsts, Language, ResourceManager,
 MemberData, MemberModel, MemberDetailView, Main;

{$R *.dfm}

procedure TfMemberQBEResultView.actDetailViewExecute(Sender: TObject);
var
 Member: TMemberModel;
 Mapper: IMemberModelMapper;
begin
 Mapper := dmMember.GetMapper;
 Member := TMemberModel.Create;
 Mapper.LoadObject(DataSet["MEMBER_ID"], Member);
 if not Assigned(fMemberDetailView) then
   fMemberDetailView := TfMemberDetailView.Create(Application, fMain.pnlClient);
 fMemberDetailView.SetData(Member, false);
 fMemberDetailView.Show;
 GCurrentView := fMemberDetailView;
end;

procedure TfMemberQBEResultView.FormCreate(Sender: TObject);
begin
 DataSet := dmMember.qQBE;
 inherited;
end;

procedure TfMemberQBEResultView.FormDestroy(Sender: TObject);
begin
 fMemberQBEResultView := nil;
 inherited;
end;

function TfMemberQBEResultView.GetRecordCount: Integer;
var
 BM: TBookmark;
begin
 with DataSet do
 begin
   DisableControls;
   BM := GetBookmark;
   try
     Last;
     Result := DataSet.RecordCount;
     GotoBookmark(BM);
   finally
     FreeBookmark(BM);
     EnableControls;
   end;
 end;
end;

procedure TfMemberQBEResultView.GridDblClick(Sender: TObject);
begin
 actDetailView.Execute;
end;

procedure TfMemberQBEResultView.LocalizeInterface;
begin
 inherited;
 CustomCaption.Caption := GetResourceString (SViewQBEResults,
   "Query by example results");
 SRecordCountCaption := GetResourceString(SQBEResultCaption,
   "%d member(s) match specified criteria");
end;

procedure TfMemberQBEResultView.UpdateRecordCount;
begin
 BriefDescription.Caption := Format(SRecordCountCaption, [RecordCount]);
end;

end.


 
Leonid Troyanovsky ©   (2007-10-16 14:28) [103]


> Игорь Шевченко ©   (16.10.07 13:54) [99]

> Уважаемый Ega23 так и не озвучил, зачем ему сабж понадобился.

Ему, видимо, поручили сопровождать группу трудящихся
освобожденного Востока :)

> в трех местах из проекта на миллион

Ладно уж, считай, что свои три строки ты отстоял :)

--
Regards, LVT.


 
Dmitry S ©   (2007-10-16 14:37) [104]

Чтото я не пойму вопроса. В методе Free выполняется как раз самостоятельное убийство объекта, т.к. Free вызывает деструктор, являясь методом. Значит аналогичным образом и можно убить объект.

Вот пример где это может понадобится:
Пусть есть какойто класс TItem, и класс TList, где организуется список этих самых TItem. Добавим к условию, что, по какимто причинам, удобнее делать так: List[n].delete, чем List.delete(n).
Тогда потребуется описать метод TItem.delete, который должен "вычеркнуть себя из списка" и убить сам себя.

Оффтоп:
> Leonid Troyanovsky ©   (15.10.07 20:12) [83]
> lv.t[&]rambler.ru

Чуть выше ваше мыло оформленно по форме, даже с "mailto:". Смысл скрывать?:)



Страницы: 1 2 3 вся ветка

Форум: "Начинающим";
Текущий архив: 2007.11.11;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.87 MB
Время: 0.058 c
2-1192455837
фыва
2007-10-15 17:43
2007.11.11
Вставка в мемо


2-1192884365
user1024
2007-10-20 16:46
2007.11.11
Как записать значение типа Memo в таблицу БД?


2-1192618151
sydenis
2007-10-17 14:49
2007.11.11
rasdial


6-1165172528
Yegorchic
2006-12-03 22:02
2007.11.11
Перехват запуска соединение по dial-up


15-1191397317
jack128_
2007-10-03 11:41
2007.11.11
news группа interbase.ibexpert.ru - не удалось соедениться с





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский