Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.11.12;
Скачать: CL | DM;

Вниз

Free and nil   Найти похожие ветки 

 
Сатир   (2006-10-23 12:58) [0]

Тут на новой работе достался по наследству код, и в нём попалась такая конструкция

freeandnil(fImportExcelNakl), где fImportExcelNakl наследник от TForm;
procedure FreeAndNil(var Obj);
var
 Temp: TObject;
begin
 Temp := TObject(Obj);
 Pointer(Obj) := nil;
 Temp.Free;
end;
Почему нельзя просто написать:
fImportExcelNakl.Free;
fImportExcelNakl:=nil;   ?


 
Плохиш ©   (2006-10-23 12:59) [1]


> Почему нельзя просто написать

А что там прямо такой запрет стоит?


 
umbra ©   (2006-10-23 13:02) [2]

можно. но это будет 2 строчки, а не одна :)


 
Сатир   (2006-10-23 13:02) [3]


> А что там прямо такой запрет стоит?

запрета нету. Есть интерес, почему нужно было так усложнять освобождение и обнуление экземпляра формы?
Может мой вариант не будет выдавать такой же результат, как и предыдущий?


 
Курдль ©   (2006-10-23 13:04) [4]


> umbra ©   (23.10.06 13:02) [2]
> можно. но это будет 2 строчки, а не одна :)


Вот именно! :)  Я тоже всегда пользовался FreeAndNil();


 
Плохиш ©   (2006-10-23 13:05) [5]


> Есть интерес, почему нужно было так усложнять освобождение

Это сделано для облегчения жизни ленивых начанающих, которые ни думать, ни читать не умеют, а бегут сюда по любому чиху. Хотя эта функция своё предназначение не выполнила.


 
Сатир   (2006-10-23 13:06) [6]

упс, не обратил внимание на название модуля.
оказывается, это реализовано в модуле SysUtils))))))


 
umbra ©   (2006-10-23 13:06) [7]


> Может мой вариант не будет выдавать такой же результат,
> как и предыдущий?
>

вариант чего?


 
Сатир   (2006-10-23 13:15) [8]

забей. вопрос исчерпан.


 
Anatoly Podgoretsky ©   (2006-10-23 13:27) [9]


> Это сделано для облегчения жизни ленивых начанающих, которые
> ни думать, ни читать не умеют, а бегут сюда по любому чиху.
>  Хотя эта функция своё предназначение не выполнила.

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


 
Rule ©   (2006-10-23 13:40) [10]

Сатир   (23.10.06 12:58)
Почему нельзя просто написать:
fImportExcelNakl.Free;
fImportExcelNakl:=nil;   ?

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


 
Сатир   (2006-10-23 14:21) [11]


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

ну тогда можно написать
try
  fImportExcelNakl.Free;
finally
  fImportExcelNakl:=nil;
end;
:-)


 
Rule ©   (2006-10-23 14:29) [12]

Сатир   (23.10.06 14:21) [11]
согласен можно, но почемуто авторов этой функции пугало использование исключений ... я просто объяснил смысл промежуточно переменной :-) нивкоем случае не настаиваю на оптимальности кода ю... мож борланд что-то страшное про исключения знает :-)


 
guav ©   (2006-10-23 14:44) [13]

> [9] Anatoly Podgoretsky ©   (23.10.06 13:27)


> это явное повторное использование переменных.

Почему же ? У меня например она применяестя для противоположной цели - для защиты от повторного использования переменной.


 
RWolf ©   (2006-10-23 14:46) [14]


>  Есть интерес, почему нужно было так усложнять освобождение
> и обнуление экземпляра формы?

По мне, так наоборот - такая конструкция упрощает освобождение. Печатать меньше.
В остальном - без разницы.


 
guav ©   (2006-10-23 14:48) [15]

> [11] Сатир   (23.10.06 14:21)

Это не эквивалент.
Возможен случай когда деструктор класса переменной вызывает другой деструктор, а в другом деструкторе пытаются сделать Free той самой переменной. Тогда FreeAndNil не приведёт к ошибке, а код [11] приведёт.


 
oldman ©   (2006-10-23 14:52) [16]


> Anatoly Podgoretsky ©   (23.10.06 13:27) [9]
> Я за все время программирования ни разу не использовал данную
> функцию, за ее ненадобностью.


+1!!!


 
Anatoly Podgoretsky ©   (2006-10-23 15:05) [17]


> Почему же ? У меня например она применяестя для противоположной
> цели - для защиты от повторного использования переменной.
>

А мы одинаково понимаем термин? У меня сомнение :-(


 
guav ©   (2006-10-23 15:14) [18]

> [9] Anatoly Podgoretsky ©   (23.10.06 13:27)


> [16] oldman ©   (23.10.06 14:52)

Допустим ситуацию - у стрелки две точки, когда пользователь удаляет одну из точек, стрелка тоже должна быть удалена. Как переписать код без этой бесполезной функции:

type
 TArrowPoint = class;
 TArrow = class;

 TArrowPoint = class(TObject)
 private
   FOwner: TArrow;
 public
   property Owner: TArrow read FOwner;
   constructor Create(Owner: TArrow);
   destructor  Destroy; override;
 end;

 TArrow = class(TObject)
 private
   FA, FB: TArrowPoint;
 public
   constructor Create;
   destructor  Destroy; override;
 end;

constructor TArrowPoint.Create(Owner: TArrow);
begin
 inherited Create;
 FOwner := Owner;
end;

destructor TArrowPoint.Destroy;
begin
 FreeAndNil(FOwner);
 inherited;
end;

constructor TArrow.Create;
begin
 inherited Create;
 FA := TArrowPoint.Create(Self);
 FB := TArrowPoint.Create(Self);
end;

destructor TArrow.Destroy;
begin
 if FB.Owner = Self then
   FB.Free;
 if FA.Owner = Self then
   FA.Free;
 inherited;
end;



> [17] Anatoly Podgoretsky ©   (23.10.06 15:05)


> А мы одинаково понимаем термин? У меня сомнение :-(

Думаю одинаково. Я имел ввиду использование FreeAndNil заместо обычного Free чтобы при попытке повторно использовать переменную получить AV практически гарантированно.


 
Anatoly Podgoretsky ©   (2006-10-23 15:18) [19]

Э у тебя тут нет переменных, а члены класса, к тому же контролируемые, для них такое понятно, и без разницы что использовать, Free/FreeAndNil
Правда такие вещи возможно лучше делать с помощью списков?


 
Сатир   (2006-10-23 15:18) [20]


> использование FreeAndNil заместо обычного Free чтобы при
> попытке повторно использовать переменную получить AV практически
> гарантированно.

вообще-то обнуляют переменную для того, чтобы срабатывала конструкция
if Assigned(переменная) then ...


 
Anatoly Podgoretsky ©   (2006-10-23 15:32) [21]


> чтобы срабатывала конструкция
> if Assigned(переменная) then ...

Вот это и есть чистое повторное использование, обнуление нужно, что бы не было ошибки при Free и конечно не для переменных, а членов класса, когда они создаются в конструкторе, а уничтожаются в деструкторе. Изредка в середине. Это не повторное использование в отличии от
if Assigned(X) then Create
В нормальной программе, без повторного использования это выглядит так
Create


 
guav ©   (2006-10-23 15:33) [22]

> для них такое понятно, и без разницы что использовать, Free/FreeAndNil

Я ошбся, когда код приводил (выбирал из реального кода, упустил кое-что). Деструктор выгляди так:
destructor TArrow.Destroy;
begin
 if FB.Owner = Self then
 begin
   FB.FOwner := nil;
   FB.Free;
 end;
 if FA.Owner = Self then
 begin
   FA.FOwner := nil;
   FA.Free;
 end;
 inherited;
end;


Тогда создание стрелки и последующее удаление точки приводит к тому, что стрелка и обе точкинормально уничтожаются.
procedure TForm1.Button1Click(Sender: TObject);
var Arrow: TArrow;
begin
 Arrow := TArrow.Create;
 Arrow.FA.Free;
end;


Замена FreeAndNil на Free недопустима - тогда будет Stack Overflow.


> Правда такие вещи возможно лучше делать с помощью списков?

Список из всегда двух элементов - стоит ли ?


 
Anatoly Podgoretsky ©   (2006-10-23 15:37) [23]

Ну так это кардинально меняет дело.


 
guav ©   (2006-10-23 15:39) [24]

Сделал поиск по генофонду.
FreeAndNil широко используется, и ладно бы всякие Indy и ActionMagagerы, FreeAndNil используется в finalization модулей classes и sysutils !
Т.к. это в finalization , речь о повторном использовании не идёт, это скорее

> [13] guav ©   (23.10.06 14:44)
> для защиты от повторного использования переменной.


 
guav ©   (2006-10-23 15:41) [25]

> [23] Anatoly Podgoretsky ©   (23.10.06 15:37)

Так как - оставить или заменить на что-то другое ?


 
Anatoly Podgoretsky ©   (2006-10-23 15:50) [26]


> Сделал поиск по генофонду.
> FreeAndNil широко используется

Это ничего не значит. Вот goto не используется, кроме одного какого то вспомогательного модуля.
Борланд ввел эту функцию, из-за многочисленных ошибок программистов, а после того как ввел, то почему бы ни использовать. Но иногда это смешно выглядит.

proc...
var
  X: ...
begin
  X := что
  FreeAndNil(X);
end;


Как такое объяснишь? И это тоже из генофонда.


 
Anatoly Podgoretsky ©   (2006-10-23 15:52) [27]


> Так как - оставить или заменить на что-то другое ?

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


 
guav ©   (2006-10-23 16:02) [28]


> Не знаю, анализ нужен, я глубоко не анализировал код, да
> и его недостаточно для анализа.

Понятно... поведение вроде спроектированно правильно, а реализацию можно поменять если вдруг окажется что "FreeeAndNil considered harmful".

> Но я в подобных случаях не ленюсь написать две явные строки.

Не тот случай, там именно FreeAndNil нужен, реализации [0].


> Как такое объяснишь?

Привычка. Может даже хорошая.
Вот я бы Free написал, а ведь Destroy там бы хватило.


 
Плохиш ©   (2006-10-23 16:07) [29]


> guav ©   (23.10.06 16:02) [28]


> Привычка. Может даже хорошая.
> Вот я бы Free написал, а ведь Destroy там бы хватило.

Вообще-то борланд в справке по Destroy все причины описал.


 
Anatoly Podgoretsky ©   (2006-10-23 16:45) [30]


> Так как - оставить или заменить на что-то другое ?

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

procedure .SetA(aValue: type);
begin
 if FA = aValue then Exit;
 if Assigned(FA) then FreeXXX
 FA := AValue или варианты


Реализация подобного рода в генотипе полно.
Это полностью контролируемое поведение и деструктуры тоже правильно будут работать.


 
Джо ©   (2006-10-23 16:48) [31]


> [30] Anatoly Podgoretsky ©


А по мне это уже преумножение сущностей. Равна переменная nil или нет — это, собственно, уже и есть флаг, зачем заводить дополнительный? Впрочем, я и сам так частенько делаю, так что камнем бросать не стану :)


 
Джо ©   (2006-10-23 16:50) [32]

Ну, "для важности" можно просто сделать:
function IsSomePropNil: Boolean
begin
 Result := Assigned (FSomeValue: TObject)
end;
8^)


 
Anatoly Podgoretsky ©   (2006-10-23 17:03) [33]

if Assigned(FA) then FreeXXX

А здесь проверка на то, надо ли освобождать или можно сразу создавать, сам процесс скрыт от пользователя и не позволяет обойти его, путем прямого обращения к FA
И это не переменная, хотя, как я уже говорил, посмотрел бы в сторону списков, но для этого надо изучать проект, может какие ни будь динамические структуры будут лучше в данном случае.


 
guav ©   (2006-10-23 19:05) [34]

> [29] Плохиш ©   (23.10.06 16:07)
> > Вот я бы Free написал, а ведь Destroy там бы хватило.
>
> Вообще-то борланд в справке по Destroy все причины описал.

Там описана только одна причина и та про применение Free в деструкторах, в коде [26] хватило бы Destroy; .


> [30] Anatoly Podgoretsky ©   (23.10.06 16:45)

Это понятно, для GDIшных хендлов такое повсеместно применяется.
Но это мне не очень подходит для данного случая (деструктор там вызывается для предка, не факт что там подвернётся именно TArrowPoint).
И я стараюсь не применять без необходимости writeable class properties, т.к. при их записи нужно смотреть реализацию, там возможны варианты.


 
Loginov Dmitry ©   (2006-10-24 00:24) [35]

Сатир   (23.10.06 12:58)
Почему нельзя просто написать:
fImportExcelNakl.Free;
fImportExcelNakl:=nil;


Этот код может оказаться потоко-небезопасным. Допустим, один объект используется в нескольких потоках. В первом потоке делаем fImportExcelNakl.Free; Далее управление может получить второй поток, код которого if Assigned(fImportExcelNakl) then <Работа с этим объектом>. AV обеспечено. Выручает процедура FreeAndNil(), которая обнуляет прежде всего ссылку, а уж после уничтожает сам объект.


 
Petr V.Abramov   (2006-10-24 00:44) [36]

> Anatoly Podgoretsky ©   (23.10.06 15:50) [26]
>   FreeAndNil(X);
> end;
> Как такое объяснишь? И это тоже из генофонда.
 так полковник Кольт тоже сделал свое изобретение, чтоб уравнять людей в правах. говорять, на его могиле так и наЧЕРТАНО :) ну и? идиоты плодятся быстрее, ибо не думают об образовании детей....


 
ИА   (2006-10-24 00:49) [37]


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


Я рекомендую FreeAndNil() как в данном случае, так и вообще как подход  к написанию кода. Во первых, имя функции "говорящее", хорошо читается. Во-вторых, короче без ущерба понятности. И в третьих, главное, зачастую вызывают только Free() если переменная одноразовая, что тоже понятно - зачем писать лишний ненужный код, что в последствии может сыграть дурную шутку - коду свойственно меняться и чем меньше надо помнить что требуется подправлять (добавить := nil; если переменная теперь будет использоваться неоднократно, а такие изменения не редки) тем лучше и безопаснее.


 
ИА   (2006-10-24 00:50) [38]


> proc...
> var
>   X: ...
> begin
>   X := что
>   FreeAndNil(X);
> end;
>
> Как такое объяснишь? И это тоже из генофонда.


не согласен. Смотрите выше...


 
Anatoly Podgoretsky ©   (2006-10-24 01:27) [39]

И в четвертых, передается нетипизированый указатель, чем полностью убивается, как рантайм, так и дизайн тайм проверка :-(
А оно надо мне такое?


 
Германн ©   (2006-10-24 02:02) [40]

Не пользовал FreeAndNil никогда, не пользую сейчас и очень сомнительно, что буду пользовать когда-нибудь. Разве что под страхом смертной казни. :-)
Меня в моём детском саду не обучили этой процедуре. Её тогда просто не существовало. Привык ходить сам, без этого костыля. А привычка - вторая натура. :-)



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

Текущий архив: 2006.11.12;
Скачать: CL | DM;

Наверх




Память: 0.58 MB
Время: 0.064 c
2-1161810212
Aleks
2006-10-26 01:03
2006.11.12
Где запретить недопустимые символы в имени файла


2-1161785055
lorn
2006-10-25 18:04
2006.11.12
Delphi->EMAIL


3-1158317143
Sergey_b
2006-09-15 14:45
2006.11.12
выбор данных, в соответствии с иерархией


15-1162011397
Rbn
2006-10-28 08:56
2006.11.12
AutoCad


1-1159518252
kyn66
2006-09-29 12:24
2006.11.12
Удалить строку из ListBox по условию