![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Использовать компоненты, но не использовать Forms.pas
DevilDevil © (2007-05-05 22:16:00)Мне интересно, есть ли в Delphi такая возможность. Есть что-то типа DataModule, на который можно брасать и настраивать компоненты, но при этом не использовать модуль Forms (не создавать и не запускать Application, ...). TComponent - это не TControl, поэтому форма ему не нужна. TDataModule - это потомок формы. Делать по аналогии с KOL достаточно сложно; нет ли более простого способа?
Ega23 (2007-05-08 14:26:00) [1]
SomeObject := TSomeObject.Create;
try
try
SomeObject.DoSomething;
except
DoSomethingOnException;
end;
finally
SomeObject.Free;
end;
Loginov Dmitry (2007-05-08 14:13:00) [2]> 1) в случае, если произошла ошибка, её надо показать
Она и так будет показана. Причем то что будет показано достаточно информативно.
> 2) ошбка может произойти в каждой из трёх строк
Это уже особенности реализации методов OnCreate и OnDestroy датамодуля. Можно сделать, чтобы ошибки не возникало. Редкий случай возникновения ошибки можно оставить на совесть механизма обработки исключений. Он должен предупредить пользователя об ошибке и удалить все ненужные объекты.
> 3) если ошибка произошла в конструкторе, то нужно показать
> и выйти из программы
Вот в конструкторе-то ее и нужно ловить. Иначе, если в OnCreate произойдет ошибка, то она будет погашена (так для форм сделано, во всяком случае), и твой try..except здесь ничего сделать не сможет.
> 4) если ошибки в конструкторе не произошло, то в любом случае
> должен быть вызван деструктор. Причём, если в деструкторе
> произошла ошибка, её нужно показать
Оставь это на совесть механизма обработки исключений.
> Вопрос: если в Run произойдёт ошибка, то до Free() произойдёт?
мдя...
В результате все сводится к этому:
DataModule1 := TDataModule1.Create(NIL);
try
DataModule1.Run();
finally
DataModule1.Free;
end;
Если нужно отформатировать текст сообщения об ошибке, то можно весь оператор try..finally заключить в try..except (но оригинальный текст сообщения об ошибке не стоит менять, пусть он написан хоть на китайском).
Reindeer Moss Eater (2007-05-08 13:41:00) [3]А просто проверить нельзя, если уж доку читать не хочется?
DevilDevil (2007-05-08 13:36:00) [4]*то Free() произойдёт?
DevilDevil (2007-05-08 13:35:00) [5]*пт, что здесь может быть неправильно, может кто либо скажет?
try
DataModule1 := TDataModule1.Create(NIL);
except
on E : Exception do ... ; // показать ошибку
Halt;
end;
TRY
try
DataModule1.Run(); // <-- Моё
except
on E : Exception do ... ; // показать ошибку
end;
FINALLY
try
DataModule1.Free;
except
on E : Exception do ... ; // показать ошибку
end;
END;
1) в случае, если произошла ошибка, её надо показать
2) ошбка может произойти в каждой из трёх строк
3) если ошибка произошла в конструкторе, то нужно показать и выйти из программы
4) если ошибки в конструкторе не произошло, то в любом случае должен быть вызван деструктор. Причём, если в деструкторе произошла ошибка, её нужно показать
Вопрос: если в Run произойдёт ошибка, то до Free() произойдёт?
Loginov Dmitry (2007-05-07 20:48:00) [6]И только Фленова, похоже.
DevilDevil (2007-05-07 18:37:00) [7]Я конечно извиняюсь... но по моему корректнее всё таки [19]. Я не прав?
Ega23 (2007-05-07 17:14:00) [8]
> Плохиш © (06.05.07 17:41) [15]
>
> Ты уже давно здесь мелькаешь, но так до сих пор не соизволил
> хоть что-нибуть прочитать...
Он Флёнова читал.
Leonid Troyanovsky (2007-05-07 11:54:00) [9]
> Kedge © (07.05.07 10:48) [29]
> Не могу понять, что в этом примере "не так".
Похоже на ошибку проектирования.
Куча ссылок на объекты, с риском потери с ними связи
при выходе из области видимости.
Если мы удерживаем к-л. ссылку, должны быть
предприняты определенные усилия по поддержанию
их валидности от момента создания, до разрушения.
Одних nil явно недостаточно, должно быть предусмотрена
обработка возникших исключений в обработчике следующего
уровня, а значит, этот обработчик должен иметь доступ
к ссылкам на созданные (несозданные) объекты.
Иными словами, приведенный в примере массив не
может быть локальной переменной, а полем (списком полей,
массивом свойств и т.п.) более глобального объекта.
Ну, и, лучше, когда этот глобальный объект озаботится
поддержанием валидности удерживаемых ссылок.
--
Regards, LVT.
Kedge (2007-05-07 10:48:00) [10][27] Leonid Troyanovsky © (07.05.07 10:25)
>Хотя, похоже, не все усвоили. См., например, [25].
Не могу понять, что в этом примере "не так".
Или, после Resource[i] := TResource.Create,
в случае возникновения исключения в конструкотре, Resource[i] может стать не nil ?
Leonid Troyanovsky (2007-05-07 10:33:00) [11]
> Loginov Dmitry © (07.05.07 10:21) [26]
> Пример:
Ты ООПрограммист или где?
Создай объект с тремя полями.
Конструктор создает, деструктор разрушает.
--
Regards, LVT.
Leonid Troyanovsky (2007-05-07 10:25:00) [12]
> DrPass © (07.05.07 02:05) [22]
> > Разница лишь в том, что try..except допускает существование
> > жизни после смерти. Путем reraise.
> Хм. А какое отношение эта мудрая мысль имеет к рассматриваемой
> проблеме?
Это к "но может быть внутри блока try...except".
Т.е., также не может.
Исключения в конструкторах оставляются обработчикам
более высокого уровня. Здесь уже это разжевали.
Хотя, похоже, не все усвоили. См., например, [25]
--
Regards, LVT.
Loginov Dmitry (2007-05-07 10:21:00) [13]> Можно привести реальный пример, когда без этого действительно
> не обойтись?
Пример:
FS1 := nil;
FS2 := nil;
FS3 := nil;
try
FS1 := TFileStream.Create(...);
FS2 := TFileStream.Create(...);
FS3 := TFileStream.Create(...);
{.......................}
finally
FS1.Free;
FS2.Free;
FS3.Free;
end;
Это иногда бывает компактнее, чем куча вложенных try...finally
Однако реально всегдаможно обойтись вложенными try...finally. Но зачем?
Kedge (2007-05-07 09:38:00) [14]> [24] Юрий Зотов © (07.05.07 09:23)
> Можно привести реальный пример, когда без этого действительно не обойтись?
Когда надо захватить мого ресурсов ?
Типа:
for i := 0 to ResCount - 1 do Resource[i] := nil;
try
for i := 0 to ResCount - 1 do Resource[i] := TResource.Create;
.............
finally
for i := 0 to ResCount - 1 do FreeAndNil(Resource[i]);
end;
Юрий Зотов (2007-05-07 09:23:00) [15]> Loginov Dmitry © (07.05.07 07:45) [23]
Можно привести реальный пример, когда без этого действительно не обойтись?
Loginov Dmitry (2007-05-07 07:45:00) [16]> Но ни в коем случае не так:
>
> try
> захватываем_какой-то_ресурс;
> ...
> finally
> освобождаем этот ресурс;
> end;
И так иногда приходится делать. Но в этом случае нужно заранее позаботится о том, чтобы программа в блоке finally не пыталась освободить незанятый ресурс. Для этого перед try пишут следующее:
какой-то_ресурс := nil;
[это я к автору, ес-но :))]
DrPass (2007-05-07 02:05:00) [17]
> Leonid Troyanovsky © (06.05.07 21:13) [17]
> Разница лишь в том, что try..except допускает существование
> жизни после смерти. Путем reraise.
Хм. А какое отношение эта мудрая мысль имеет к рассматриваемой проблеме?
Юрий Зотов (2007-05-07 00:41:00) [18]> DevilDevil © (06.05.07 15:17) [12]
> А если raise произойдёт в TDataModule1.OnCreate() ?
То произойдет следующее:
- объект создан не будет;
- переменная DataModule1 не получит верного значения;
- исключение будет передано в Ваш код;
- если Create стоит ВНУТРИ try, то исполнение перейдет в секцию finally, а там Free даст ВТОРОЕ исключение;
- если Create стоит ПЕРЕД try, то ВЕСЬ блок try-finally будет обойден и второго исключения не возникнет.
Золотое правило механики:
захватываем_какой-то_ресурс;
try
...
finally
освобождаем этот ресурс;
end;
Но ни в коем случае не так:
try
захватываем_какой-то_ресурс;
...
finally
освобождаем этот ресурс;
end;
Потому что если при захвате ресурса возникло исключение, то захвачен он не будет - значит, и освобождать нечего.
Loginov Dmitry (2007-05-06 23:44:00) [19]правильно так:
DataModule1 := TDataModule1.Create(NIL);
try
// Твое
finally
DataModule1.Free;
end;
DevilDevil (2007-05-06 23:39:00) [20]Т.е так:
try
DataModule1 := TDataModule1.Create(NIL);
except
on E : Exception do ... ; // показать ошибку
Halt;
end;
TRY
try
DataModule1.Run(); // <-- Моё
except
on E : Exception do ... ; // показать ошибку
end;
FINALLY
try
DataModule1.Free;
except
end;
END;