Быстрее ли проверять существование файла до загрузки или улавливать исключение, если оно не существует?
Мне было рекомендовано использовать второй вариант try-except, но я также хотел бы знать, что думают другие: какая процедура из двух ниже (если таковая имеется) более эффективна по времени?
procedure LoadImage(img: TImage; filename: string);
begin
if fileexists(filename) then
img.Picture.Loadfromfile(filename)
else
img.Picture.Loadfromfile('default.jpg')
end;
или
procedure LoadImage(img: TImage; filename: string);
begin
try
img.Picture.Loadfromfile(filename)
except
img.Picture.Loadfromfile('default.jpg')
end
end;
Ответы
Ответ 1
Забудьте эффективность. Читаемость кода - это путь, более важный. Преждевременная оптимизация - это корень всех видов зла.
Первое ясно в своих намерениях. Каждый может легко понять, что происходит.
Второй заставляет меня остановиться и пойти "Что...?"
Вы никогда не захотите, чтобы ваш код вызывал вторую реакцию.
Ответ 2
Если эффективность времени - это ваши единственные критерии, первая из них будет быстрее, потому что обработка исключений занимает процессор.
FileExists() использует один вызов WinApi, поэтому его быстро, но он проверяет только, существует ли файл.
Если файл существует, но его в неправильном формате или его заблокирован другим потоком, вы получите необработанное исключение.
Ответ 3
Одна проблема с вашим вопросом заключается в том, что вы не указали желаемую семантику. Есть две возможные интерпретации, и какое решение лучше, зависит от этого выбора. Я предполагаю, что не могу загрузить резервную копию, является фатальной ошибкой.
- Если первый файл существует, загрузите его, иначе загрузите второй. Если первый файл существует, но не может быть загружен, выведите сообщение об ошибке.
- Если первый файл не может быть загружен, вернитесь ко второму.
Если вам нужна семантика 1) ваш первый код в порядке.
Если вам нужна семантика 2), то ни одна из них не является хорошей. Первый код не имеет семантики, потому что:
- У этого есть условие гонки. Если изображение будет удалено между проверкой существования файла и его загрузкой, оно не удастся.
- Если файл существует, но не может быть загружен, генерируется исключение. Это может произойти, если файл не является допустимым или не может быть открыт.
Второй использует исключения для общего случая, что плохо.
Итак, чтобы достичь второй семантики, я бы использовал:
procedure LoadImage(img: TImage; filename: string);
var success:boolean;
begin
success := false;
if FileExists(filename)
then try
img.Picture.LoadFromFile(filename);
success := true;
except
end
if not success
then img.Picture.LoadFromFile('default.jpg');
end;
Проверка наличия перед открытием делает ошибку более быстрой, но случай успеха медленнее. Так какой из них быстрее зависит от вашего использования.
Лично я использую третий вариант во втором, даже если изображение иногда отсутствует, поскольку я считаю, что нормально работающее приложение не должно генерировать исключения. Я бы позаботился о производительности, если бы бенчмаркинг показал, что это заметно.
Вы также должны рассмотреть предложение более целенаправленного исключения. Одеяло, улавливающее все исключения, - плохой стиль. К сожалению, я не смог найти четкую спецификацию, исключения которой выбраны TPicture.LoadFromFile
, поэтому я оставлю сейчас в объявлении обложки.