Home All Groups Group Topic Archive Search About

test bit flags that aren't set?

Author
29 Jun 2005 8:55 PM
Craig Buchanan
I'm trying to determine if a flag has been set AsDirty or not.  If it isn't
set to AsDirty, I want to exit the sub.  When the flag is 0, I can't seem to
get the test working correctly.

Can someone see the errors of my ways?  See code below.

Thanks,

Craig

<code>
Public Enum ClassMarked
    AsUnmarked = 0
    AsDirty = 1
    AsNew = 2
    AsTrash = 4
End Enum

'assume m_Flags hasn't been set
Private m_Flags As ClassMarked

'this test should make the code exit; doesn't work
If m_Flags And Not ClassMarked.AsDirty Then Exit Sub

'this test should make the code exit; also doesn't work
If m_Flags And ClassMarked.AsUnmarked Then Exit Sub

</code>

Author
29 Jun 2005 9:16 PM
Duane Bozarth
Craig Buchanan wrote:
Show quoteHide quote
>
> I'm trying to determine if a flag has been set AsDirty or not.  If it isn't
> set to AsDirty, I want to exit the sub.  When the flag is 0, I can't seem to
> get the test working correctly.
>
> Can someone see the errors of my ways?  See code below.
>
> Thanks,
>
> Craig
>
> <code>
> Public Enum ClassMarked
>     AsUnmarked = 0
>     AsDirty = 1
>     AsNew = 2
>     AsTrash = 4
> End Enum
>
> 'assume m_Flags hasn't been set
> Private m_Flags As ClassMarked
>
> 'this test should make the code exit; doesn't work
> If m_Flags And Not ClassMarked.AsDirty Then Exit Sub
>
> 'this test should make the code exit; also doesn't work
> If m_Flags And ClassMarked.AsUnmarked Then Exit Sub
>
> </code>

I think it's poor practice to code against anything that isn't set,
but...

As I interpret what VB would do in the above cases, both would evaluate
to 0 which is False and so neither If clause would fire...
Author
29 Jun 2005 9:18 PM
Ken Halter
"Craig Buchanan" <msnews.microsoft.com> wrote in message
news:%235yFdzOfFHA.3788@tk2msftngp13.phx.gbl...
> I'm trying to determine if a flag has been set AsDirty or not.  If it
> isn't
> set to AsDirty, I want to exit the sub.  When the flag is 0, I can't seem
> to
> get the test working correctly.
>

Try something like.....
'============
Private Sub Form_Load()

   m_Flags = AsDirty Or AsNew 'AsDirty set

   If (m_Flags Or ClassMarked.AsDirty) = m_Flags Then
      MsgBox "AsDirty Set"
   End If

   m_Flags = AsNew 'AsDirty clear

   If (m_Flags Or ClassMarked.AsDirty) <> m_Flags Then
      MsgBox "AsDirty Clear"
   End If

   '*********************

   m_Flags = AsDirty Or AsNew 'AsDirty set

   If (m_Flags And ClassMarked.AsDirty) = ClassMarked.AsDirty Then
      MsgBox "AsDirty Set"
   End If

   'Clear the flag (this is where "And Not" comes in handy)
   m_Flags = (m_Flags And Not ClassMarked.AsDirty) 'AsDirty clear

   If (m_Flags And ClassMarked.AsDirty) <> ClassMarked.AsDirty Then
      MsgBox "AsDirty Clear"
   End If

End Sub
'============

--
Ken Halter - MS-MVP-VB - http://www.vbsight.com
DLL Hell problems? Try ComGuard - http://www.vbsight.com/ComGuard.htm
Please keep all discussions in the groups..
Author
30 Jun 2005 11:09 AM
MikeD
Show quote Hide quote
"Craig Buchanan" <msnews.microsoft.com> wrote in message
news:%235yFdzOfFHA.3788@tk2msftngp13.phx.gbl...
> I'm trying to determine if a flag has been set AsDirty or not.  If it
> isn't
> set to AsDirty, I want to exit the sub.  When the flag is 0, I can't seem
> to
> get the test working correctly.
>
> Can someone see the errors of my ways?  See code below.
>
> Thanks,
>
> Craig
>
> <code>
> Public Enum ClassMarked
>    AsUnmarked = 0
>    AsDirty = 1
>    AsNew = 2
>    AsTrash = 4
> End Enum
>
> 'assume m_Flags hasn't been set
> Private m_Flags As ClassMarked
>
> 'this test should make the code exit; doesn't work
> If m_Flags And Not ClassMarked.AsDirty Then Exit Sub
>
> 'this test should make the code exit; also doesn't work
> If m_Flags And ClassMarked.AsUnmarked Then Exit Sub


Nope.  That's not right.  You want this:

If (m_Flags And AsDirty) <> AsDirty Then
    Exit Sub
End If

If (m_Flags And AsUnmarked) = AsUnmarked Then
    Exit Sub
End If


--
Mike
Microsoft MVP Visual Basic
Author
30 Jun 2005 1:45 PM
Larry Serflaten
"Craig Buchanan" <msnews.microsoft.com> wrote

> I'm trying to determine if a flag has been set AsDirty or not.  If it isn't
> set to AsDirty, I want to exit the sub. 

If Not (mFlags And AsDirty) Then Exit Sub

Or:

If (mFlags And AsDirty) = False Then Exit Sub


LFS
Author
30 Jun 2005 5:20 PM
Jim Mack
Larry Serflaten wrote:
> "Craig Buchanan" <msnews.microsoft.com> wrote
>
>> I'm trying to determine if a flag has been set AsDirty or not.  If
>> it isn't set to AsDirty, I want to exit the sub.
>
> If Not (mFlags And AsDirty) Then Exit Sub
>
> Or:
>
> If (mFlags And AsDirty) = False Then Exit Sub
>
>
> LFS

Unless VB is reading my mind (again), I wouldn't use either of those, because the result of (mFlags And AsDirty) isn't a boolean, and the code is assuming that it is.

The first of those should fail big time, the second not so much. "= 0" would be clearer, and would avoid communicating that boolean assumption.

To be squeaky clean, you'd have to say:

If Not CBool(mFlags And AsDirty) Then


Or Not? :-)

--
        Jim
Author
30 Jun 2005 9:37 PM
Larry Serflaten
"Jim Mack" <jmack@mdxi.nospam.com> wrote

> Unless VB is reading my mind (again), I wouldn't use either of those,
> because the result of (mFlags And AsDirty) isn't a boolean, and the
> code is assuming that it is.

Its not the code that is making the assumtions there...  ;-)

> The first of those should fail big time, the second not so much.

I forgot to include the CBool() part.  Good catch, thanks!

LFS
Author
1 Jul 2005 1:55 PM
Tony Proctor
I think Jim has already caught this but it's a bit dangerous to mix real
booleans with simple zero/non-zero tests. I always code the tests according
to what they're really doing, bit-wise, e.g.

If  (mFlags And AsDirty) = 0 Then

or

If (mFlags And AsDirty) <> 0 Then

The only time you need the bitmask name on the right-hand side as well (as
others have suggested), e.g.

If (mFlags And AsDirty) = AsDirty Then

is if that bitmask contains more than a single bit, and of course you're
testing for "all" rather than "any" of the bits.

        Tony Proctor

Show quoteHide quote
"Larry Serflaten" <serfla***@usinternet.com> wrote in message
news:eKVShlXfFHA.1048@tk2msftngp13.phx.gbl...
>
> "Craig Buchanan" <msnews.microsoft.com> wrote
>
> > I'm trying to determine if a flag has been set AsDirty or not.  If it
isn't
> > set to AsDirty, I want to exit the sub.
>
> If Not (mFlags And AsDirty) Then Exit Sub
>
> Or:
>
> If (mFlags And AsDirty) = False Then Exit Sub
>
>
> LFS
>
>
>
Author
1 Jul 2005 1:59 PM
Tony Proctor
In your ClassMarked Enum, Craig, you need to change AsUnmarked so that all
your bit masks have non-zero values. A mask of 0 isn't actually a mask of
anything, and will cause run-time failures if you try to use it as such.

For instance:

Public Enum ClassMarked
    AsUnmarked = 1
    AsDirty = 2
    AsNew = 4
    AsTrash = 8
End Enum

or, as I prefer to code such bitmak Enums:

Public Enum ClassMarked
    AsUnmarked = 2^0
    AsDirty = 2^1
    AsNew = 2^2
    AsTrash = 2^3
End Enum

which is identical, but more readable

        Tony Proctor

Show quoteHide quote
"Craig Buchanan" <msnews.microsoft.com> wrote in message
news:#5yFdzOfFHA.3788@tk2msftngp13.phx.gbl...
> I'm trying to determine if a flag has been set AsDirty or not.  If it
isn't
> set to AsDirty, I want to exit the sub.  When the flag is 0, I can't seem
to
> get the test working correctly.
>
> Can someone see the errors of my ways?  See code below.
>
> Thanks,
>
> Craig
>
> <code>
> Public Enum ClassMarked
>     AsUnmarked = 0
>     AsDirty = 1
>     AsNew = 2
>     AsTrash = 4
> End Enum
>
> 'assume m_Flags hasn't been set
> Private m_Flags As ClassMarked
>
> 'this test should make the code exit; doesn't work
> If m_Flags And Not ClassMarked.AsDirty Then Exit Sub
>
> 'this test should make the code exit; also doesn't work
> If m_Flags And ClassMarked.AsUnmarked Then Exit Sub
>
> </code>
>
>
Author
1 Jul 2005 2:47 PM
Craig Buchanan
Thanks everyone for their input.  These lines work as I would expect:

    A:    If (m_Flags And ClassMarked.AsDirty) <> ClassMarked.AsDirty Then
Exit Sub
    B:    If Not CBool(m_Flags And ClassMarked.AsDirty) Then Exit Sub

Is the consensus then B is better than A?  When trying to determine if no
flags have been set, is it better practice to compare to 0, to the negation
of a specific bit or to an 'unmarked' bit (like Tony and Duane's
AsUnmarked)?

Thanks again for all the insight.

Craig

Show quoteHide quote
"Craig Buchanan" <msnews.microsoft.com> wrote in message
news:%235yFdzOfFHA.3788@tk2msftngp13.phx.gbl...
> I'm trying to determine if a flag has been set AsDirty or not.  If it
isn't
> set to AsDirty, I want to exit the sub.  When the flag is 0, I can't seem
to
> get the test working correctly.
>
> Can someone see the errors of my ways?  See code below.
>
> Thanks,
>
> Craig
>
> <code>
> Public Enum ClassMarked
>     AsUnmarked = 0
>     AsDirty = 1
>     AsNew = 2
>     AsTrash = 4
> End Enum
>
> 'assume m_Flags hasn't been set
> Private m_Flags As ClassMarked
>
> 'this test should make the code exit; doesn't work
> If m_Flags And Not ClassMarked.AsDirty Then Exit Sub
>
> 'this test should make the code exit; also doesn't work
> If m_Flags And ClassMarked.AsUnmarked Then Exit Sub
>
> </code>
>
>
Author
1 Jul 2005 2:55 PM
Ken Halter
Show quote Hide quote
"Craig Buchanan" <msnews.microsoft.com> wrote in message
news:e6iuXvkfFHA.3612@TK2MSFTNGP12.phx.gbl...
> Thanks everyone for their input.  These lines work as I would expect:
>
>    A:    If (m_Flags And ClassMarked.AsDirty) <> ClassMarked.AsDirty Then
> Exit Sub
>    B:    If Not CBool(m_Flags And ClassMarked.AsDirty) Then Exit Sub
>
> Is the consensus then B is better than A?  When trying to determine if no
> flags have been set, is it better practice to compare to 0, to the
> negation
> of a specific bit or to an 'unmarked' bit (like Tony and Duane's
> AsUnmarked)?
>
> Thanks again for all the insight.
>
> Craig

fwiw, imo, the one that's easier for you to read, especially when you
re-read several months from now, should be the one to use. Personally, I
don't like the "If this <> that then exit sub" syntax.... but that's me. We
just went through this in another thread so.... all I'll say is "There's
only one way in to a procedure so there should only be one way out of a
procedure" ;-) ymmv

--
Ken Halter - MS-MVP-VB - http://www.vbsight.com
DLL Hell problems? Try ComGuard - http://www.vbsight.com/ComGuard.htm
Please keep all discussions in the groups..
Author
1 Jul 2005 7:42 PM
Larry Serflaten
"Craig Buchanan" <msnews.microsoft.com> wrote
> Thanks everyone for their input.  These lines work as I would expect:
>
>     A:    If (m_Flags And ClassMarked.AsDirty) <> ClassMarked.AsDirty Then
> Exit Sub
>     B:    If Not CBool(m_Flags And ClassMarked.AsDirty) Then Exit Sub
>
> Is the consensus then B is better than A? 

You may not find everyone in agreement for a 'consensus'.  Also you have not
covered all possible methods.  For ease of reading it is advisable to stay working
on the True side, so that equations equate to True, instead of comparing them to
0, or using the Not operator.  In this case, instead of:

Sub X()
  If Not CBool(mFlags And AsDirty) Then Exit Sub
  '  ... other code  ...
End Sub

It may be easier to read if you use this:

Sub Y()
  If mFlags And AsDirty Then
    ' ... other code  ...
  End If
End Sub


> When trying to determine if no
> flags have been set, is it better practice to compare to 0, to the negation
> of a specific bit or to an 'unmarked' bit (like Tony and Duane's
> AsUnmarked)?

See the above comment, working with True conditions is 'generally' easier
to follow for most people.

Could you get by using an Enum like:

> > Public Enum ClassMarked
> >     AsNew = 0
> >     AsTrash = 1
> >     AsDirty = 2
> > End Enum

Also (perhaps in other situations) if you often test for one or more conditions,
then don't hesitate to add them into your Enum:

Public Enum ClassMarked
    AsNew = 0
    AsTrash = 1
    AsDirty = 2
    AsNotNew = Not AsNew
End Enum

Or more specifically:

Public Enum Direction
  Stopped = 0
  North = 1
  South = 2
  East = 4
  West = 8
  Vertical = North Or South
  Horizontal = East Or West
  Moving = Not Stopped
End Enum

Use as you see fit!

LFS