27 марта 2011 г.

Задачка №9

Что не так в этом коде?
var
  Enum: IEnumVariant;
  Item: Variant;
  Value: LongWord;
begin
  ...
  while Enum.Next(1, Item, Value) = 0 do
  begin
  end;
Я думаю, что это до боли знакомый код многим. Я думаю, что почти все пробовали WMI. И не менее знакомы стенания по нему программистов, копирующих его один-к-одному, не удосужившись заглянуть в документацию и подумать головой.

Спокойно, в этой задачке нет никаких багов в Delphi или ещё каких подводных камней. Это простая задачка на умение читать MSDN и объяснять поведение.

Итак: какие-же стенания несчастных копипастеров мы можем услышать по этому коду, что в нём не так и как это исправить?

Ответ на задачку будет выложен как обычно: примерно через месяц.

Ответ.

3 комментария :

  1. тут все нормально, только Reset надо вначале сделать, если нужно перебрать элементы с самого начала

    ОтветитьУдалить
  2. Я не дельфист, поэтому мне сложно сказать, не является ли ошибкой указывать вторым параметром простую переменную, тогда как MSDN говорит о массиве. Даже при том, что один элемент и запрашивается. Вероятно, в прототипе дельфисткого интерфейса там указан открытый массив, и компилятор автоматически приводит типы. Но поскольку явно сказано, что проблема не в Дельфи, видимо тут всё нормально.
    Другое дело, что третий параметр, являясь опциональным и при этом указателем, может быть опущен путём указания NULL. Ну в смысле Nil. А значит в прототипе должен стоять указатель. Здесь же передаётся простая переменная. Не думаю, что компилятор под капотом незаметно позволяет сводить объекты к указателям на них, так что раз скомпилилось, значит реализация, упрощая жизнь дельфистам, принимает третий параметр по ссылке, что делает невозможным его опциональность.
    Ну ещё меня коробит от сравнения с 0. Мне пришлось покопаться в Win SDK, чтобы вспомнить, что S_OK действительно равен нулю.

    ОтветитьУдалить
  3. Ну во-первых - это использование Item: Variant; вместо Item: OleVariant; что как бы чревато. Я даже не уверен скомпилируется ли это. Ну и я бы еще в конце цикла я бы поставил:
    while Enum.Next(1, Item, Value) = 0 do
    begin
    //тут что то делаем
    VariantClear(Item);
    end;

    p.s. ну и есстественно должна быть проверка assigned(Enum) и VariantClear(Item); если Item до этого использовался в функции.

    ОтветитьУдалить

Можно использовать некоторые HTML-теги, например:

<b>Жирный</b>
<i>Курсив</i>
<a href="http://www.example.com/">Ссылка</a>

Вам необязательно регистрироваться для комментирования - для этого просто выберите из списка "Анонимный" (для анонимного комментария) или "Имя/URL" (для указания вашего имени и (опционально) ссылки на сайт). Все прочие варианты потребуют от вас входа в вашу учётку (поддерживается OpenID).

Пожалуйста, по возможности используйте "Имя/URL" вместо "Анонимный". URL можно просто не указывать.

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