Нежданчик: with НЕ экранирует собственные проперти в методе

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

Ответить
Аватара пользователя
Cheb
энтузиаст
Сообщения: 994
Зарегистрирован: 06.06.2005 15:54:34
Контактная информация:

Нежданчик: with НЕ экранирует собственные проперти в методе

Сообщение Cheb »

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

Код: Выделить всё

  procedure TTextureLikeAsset.Devour(c: TGenericAsset);
  begin
    with (c as TTextureLikeAsset) do begin
      f_width:= Width;
      f_height:= Height;
    end;
    inherited Devour(c);
  end;

- и прилетела мне птица обломинго. :x Компилятор засчитал Width как Self.Width, и программа душераздирающе упала уже в рантайме.

Пришлось заменить на

Код: Выделить всё

  procedure TTextureLikeAsset.Devour(c: TGenericAsset);
  begin
    f_width:= (c as TTextureLikeAsset).Width;
    f_height:= (c as TTextureLikeAsset).Height;
    inherited Devour(c);
  end;

- и всё пучком.
А если там таких полей стопицот? Компилятор догадается соптимизировать вызовы as? Сомневаюсь. :(
Аватара пользователя
hinst
энтузиаст
Сообщения: 781
Зарегистрирован: 12.04.2008 18:32:38

Сообщение hinst »

сделай переменную; либо только первый вызов as, а все последующие - ()
Аватара пользователя
Cheb
энтузиаст
Сообщения: 994
Зарегистрирован: 06.06.2005 15:54:34
Контактная информация:

Сообщение Cheb »

сделай переменную;

Строго говоря, в моём случае вес as пренебрежим (поскольку сопровождает или "толстое" обращение к OpenGL или загрузку полсотни мегабайт с диска).

Я просто хотел поделиться подводным камнем :(

а все последующие - ()

Ы :?: :(

Добавлено спустя 1 минуту 50 секунд:
Re: Нежданчик: with НЕ экранирует собственные проперти в методе
:!: Я ещё думал: может, это баг? С дельфёй есть кто-нить, проверить?
pupsik
энтузиаст
Сообщения: 1154
Зарегистрирован: 20.08.2014 16:20:13
Контактная информация:

Сообщение pupsik »

душащей меня жабы
жаба хороша - писанины меньше... :D

Код: Выделить всё

      f_width:= Width;
      f_height:= Height;
и какая версия фпс и лазаря сие делает. И это только в одной системе (?) или везде...
Просто не замечал подобного.

либо только первый вызов as, а все последующие - ()
а можно пример, а то чет туплю :oops:
sign
энтузиаст
Сообщения: 1131
Зарегистрирован: 30.08.2009 09:20:53

Сообщение sign »

Cheb писал(а):Нарвался пытаясь сэкономить (не корысти ради, а только велением душащей меня жабы) на вызове as.

Код: Выделить всё

  procedure TTextureLikeAsset.Devour(c: TGenericAsset);
  begin
    with (c as TTextureLikeAsset) do begin
      f_width:= Width;
      f_height:= Height;
    end;
    inherited Devour(c);
  end;

- и прилетела мне птица обломинго. :x Компилятор засчитал Width как Self.Width, и программа душераздирающе упала уже в рантайме.

Пришлось заменить на

Код: Выделить всё

  procedure TTextureLikeAsset.Devour(c: TGenericAsset);
  begin
    f_width:= (c as TTextureLikeAsset).Width;
    f_height:= (c as TTextureLikeAsset).Height;
    inherited Devour(c);
  end;

- и всё пучком.
А если там таких полей стопицот? Компилятор догадается соптимизировать вызовы as? Сомневаюсь. :(

Странно.
Я мне приходится дописывать Self. И именно потому, что в with цепляются не Self.Width, а width параметра.
IDE 1.2.6
FPC 2.6.4
Windows XP3
Аватара пользователя
Alexx2000
постоялец
Сообщения: 490
Зарегистрирован: 25.10.2006 00:22:07
Откуда: Мытищи
Контактная информация:

Сообщение Alexx2000 »

pupsik писал(а):а можно пример, а то чет туплю :oops:

Код: Выделить всё

    f_width:= (c as TTextureLikeAsset).Width;
    f_height:= TTextureLikeAsset(c).Height;
Аватара пользователя
Cheb
энтузиаст
Сообщения: 994
Зарегистрирован: 06.06.2005 15:54:34
Контактная информация:

Сообщение Cheb »

Мне очень стыдно, что не додумался сам :oops:

Конечно же! Весь смысл оператора as - поднять исключение если попадётся левый класс не из той ветки наследования.
Все последующие as просто не имеют физического смысла: либо класс подходит и достаточно тупого тайпкаста, либо исключение уже было поднято, и исполнение дотуда просто не дошло :facepalm: Ну я тупооой :cry:
Аватара пользователя
Stertor
новенький
Сообщения: 20
Зарегистрирован: 10.08.2014 18:11:12
Контактная информация:

Сообщение Stertor »

with (c as TTextureLikeAsset) do begin
:facepalm: :facepalm: :facepalm: :facepalm: :facepalm:
MylnikovDm
постоялец
Сообщения: 103
Зарегистрирован: 15.02.2007 20:26:10
Откуда: Челябинск

Сообщение MylnikovDm »

а вариант with TTextureLikeAsset(c) do begin
работает правильно?
Если да, то может переделать на явную проверку совместимости типа?

Код: Выделить всё

if c is TTextureLikeAsset then  
  with TTextureLikeAsset(c) do begin
  ...
  end;

если вам так уж нужно генерирование исключения, то добавте секцию else и сгенерируйте его там.

Другой вариант, сделать локальную переменную нужного типа, присвоить её через as, а дальше воткнуть в with

Код: Выделить всё

procedure TTextureLikeAsset.Devour(c: TGenericAsset);
var
  t: TTextureLikeAsset;
begin
    t := c as TTextureLikeAsset;
    with t do begin
      f_width:= Width;
      f_height:= Height;
    end;
    inherited Devour(c);
  end;
Аватара пользователя
Tango
постоялец
Сообщения: 162
Зарегистрирован: 31.05.2012 17:07:30

Сообщение Tango »

Считаю with вредным и опасным, как раз из-за вот такой непредсказуемости.
Ответить