Флаги в VB6 не возвращают правильное значение

В настоящее время я пытаюсь использовать перечисление битового флага в проекте VB6/COM. Однако при попытке прочитать значения из перечисления я получаю противоречивые результаты.

Вот определение перечисления:

Enum Fruits
    None = 0
    Apple = 1
    Strawberry = 2
    Lemon = 4
End Enum

У меня есть объект, который предоставляет свойство типа Fruits

Public Get AvailableFruits as Fruits

Код, который должен уметь читать значение, используется для отображения/скрытия метки в зависимости от значений каждого бита перечисления:

lblAppleAvailable.Visible = basket.AvailableFruits And Fruits.Apple

Когда этот код выполняется и у меня есть basket.AvailableFruits = 0, в результате я получаю True.

Любая идея о том, что может вызвать такое поведение?

Редактировать :

Я пробовал с разными значениями перечисления:

basket.AvailableFruits = 0
basket.AvailableFruits And Apple        // Returns True
basket.AvailableFruits And Strawberry   // Returns True
basket.AvailableFruits And Lemon        // Returns False

В качестве побочного узла при отладке кода, если я помещаю выражение в выражение наблюдения, я получаю правильное значение; но когда выражение оценивается в моем коде, оно все равно возвращает True.

Я попытался использовать другой синтаксис проверки:

(basket.AvailableFruits And Fruits.Apple) = Fruits.Apple

Все еще получает True, когда basket.AvailableFruits = 0 :-(

Решение

После тестирования различных решений я смог сузить проблему до COM-компонента. Первоначальный кодировщик этого компонента имел указатель, установленный на 0, вместо того, чтобы возвращать 0 в качестве значения, что вызывало проблему при попытке прочитать значение.

Я выбрал ответ FlipScript из-за вспомогательной функции, которая кажется хорошим советом для улучшения читаемости кода.


person Thibault Falise    schedule 07.01.2011    source источник
comment
Какой у вас код для basket.AvailableFruits?   -  person LittleBobbyTables - Au Revoir    schedule 07.01.2011
comment
@LBT: у меня нет доступа к реальному коду свойства, оно является частью COM-объекта, закодированного на C++.   -  person Thibault Falise    schedule 07.01.2011
comment
Итак, когда AvailableFruits = 0, то в случае с Apple (0 AND 1) = True? Однако в случае с лимоном (0 И 4) = False? Хммм.... Здесь может быть что-то большее, чем проверка битового поля...   -  person Flipster    schedule 07.01.2011
comment
У меня была возможность проверить код свойства: на данный момент оно не реализовано и всегда возвращает 0.   -  person Thibault Falise    schedule 07.01.2011
comment
Ха-ха, по крайней мере, теперь вы знаете, как написать свою часть кода, когда он, наконец, будет реализован!   -  person Cody Gray    schedule 07.01.2011
comment
Да, но это не объясняет странный результат, который я получил с тестами 1, 2 и 4 :-(   -  person Thibault Falise    schedule 07.01.2011
comment
Я рекомендую вам проверить, что вы определенно видите это поведение. Мне это кажется невозможным. Проверьте, есть ли какой-либо другой код, который устанавливает видимость метки, меняете ли вы правильную метку... Если вы действительно получаете такое поведение, я могу только думать, что ваш C COM-объект записывает неверный указатель и полностью накручивает Среда выполнения VB6. Теоретически возможно, что это может вызвать что-то настолько странное, но я не видел, чтобы это происходило.   -  person MarkJ    schedule 08.01.2011
comment
Должен ли быть basket.AvailableFruits = 0, поскольку 0 не является значением для перечисления Fruits?   -  person Brian Hooper    schedule 10.01.2011
comment
@Brian Hooper: Плохо, перечисление имеет значение 0, но я не включил его в свой вопрос. Исправлено !   -  person Thibault Falise    schedule 10.01.2011


Ответы (2)


Чтобы проверить значение флага, используйте что-то вроде этого:

lblAppleAvailable.Visible = (basket.AvailableFruits And Fruits.Apple) = Fruits.Apple

После того, как вы выполните «И», вам все равно нужно увидеть, равно ли полученное значение значению флага (или чему-то другому, кроме 0, на самом деле).

Вы также можете создать небольшую вспомогательную функцию:

Private Function HasFruitFlag(Check As Fruits, Flag As Fruits) As Boolean
    HasFruitFlag (Check And Flag) = Flag
End Function

И вы могли бы назвать это так:

lblAppleAvailable.Visible = HasFruitFlag(basket.AvailableFruits, Fruits.Apple)
person Flipster    schedule 07.01.2011
comment
+1 это правильно. Вы просто опередили меня, чтобы опубликовать то же самое. - person Cody Gray; 07.01.2011
comment
Я пытался сравнить полученное значение с 0 (((basket.AvailableFruits And Fruits.Apple) ‹› 0), но безуспешно. Попробую ваш метод. - person Thibault Falise; 07.01.2011
comment
Я думаю, что это неправильно. В исходном коде VB6 будет неявно приводить целочисленный результат побитовой операции И к логическому значению. Ноль будет преобразован в False, а любое ненулевое значение будет преобразовано в True. Это изменение кода не изменит результат выражения. - person MarkJ; 08.01.2011
comment
У меня была возможность проверить код свойства: в настоящее время оно не реализовано и всегда возвращает 0. - лол. Что ж, это объясняет, почему проверка флагов не работает! В любом случае, когда вам нужна вспомогательная функция для выполнения работы после того, как это свойство будет исправлено, это должно сделать это. - person Flipster; 10.01.2011
comment
MarkJ - Я понятия не имею, что вы имели в виду... VB6 не принуждает неявно целые числа, которые выполняли побитовые операции над логическими значениями. Вспомогательная функция, которую я написал выше, представляет собой сравнение на равенство, которое явно возвращает логическое значение. - person Flipster; 10.01.2011
comment
Я только что попробовал это решение, и оно не решило проблему. Я постараюсь посмотреть на получателя собственности, чтобы увидеть, происходит ли что-то там. - person Thibault Falise; 10.01.2011
comment
@FlipScript: Ну, даже если я получаю 0 при каждом вызове, это не объясняет, почему я получаю True при оценке выражения (1 And 0) ‹› 0 ;-) - person Thibault Falise; 10.01.2011

Попробуйте использовать локальный var

    Dim LocalFruits As Fruits

    LocalFruits = basket.AvailableFruits
    Debug.Print (LocalFruits And Apple) <> 0
    Debug.Print (LocalFruits And Strawberry) <> 0
    Debug.Print (LocalFruits And Lemon) <> 0

Кроме того, вы можете использовать менее подверженное ошибкам объявление перечисления, подобное этому

Enum Fruits
    Apple = 2 ^ 0
    Strawberry = 2 ^ 1
    Lemon = 2 ^ 2
End Enum
person wqw    schedule 08.01.2011