|
-
Jul 22nd, 2010, 05:14 PM
#1
Thread Starter
Frenzied Member
How to get assigned enums with OR?
I realize this is probably trivial, but for some reason I'm not sure how to pull it off. Say I have the following enum:
Code:
Public Enum FlagType
Docs
Email
Web
End Enum
And I assign multiple FlagType using OR like:
Code:
Dim flags as FlagType = FlagType.Docs Or FlagType.Email
How do I then at runtime determine which flags where set for flags? In this example, it should be Docs and Email.
-
Jul 22nd, 2010, 05:36 PM
#2
Re: How to get assigned enums with OR?
In order to use enums like that, you'll have to declare them as bitfields:
Code:
Public Enum FlagType
Docs = 1
Email = 2
Web = 4
End Enum
ie. continously doubling the values (allowing the bits to effectively function as light-switches). You can set them using either bitwise Or (like you did) or +, and read them using bitwise And:
Code:
if flags AND FlagType.Docs <> 0 then ...
The method of implementing True/False information in this way was very important 20 years ago, since storage was a constant issue. Nowadays it is common to store True/False values as 32/64 bit integers in databases, and bitfields aren't as widely used. Still it's a neat little way to compact information into a single variable.
Regards Tom
-
Jul 22nd, 2010, 09:52 PM
#3
Fanatic Member
Re: How to get assigned enums with OR?
You are trying to DECLARE the variable flags as one of two possible choices.
While ThomasJohnsen indicated one option for ACCCESING the value of the variable flags, it seems to me you are overcomplicating things a bit.
The enum is a collection of constants, right (kind of). your variable flags should be declared as follows (the code is pretty meaningless, but it demonstrates how to handle your enum values in a variable . . .):
Code:
Public Enum FlagType
Docs = 1
Email = 2
Web = 3
End Enum
Public Class FlagHandler
Dim MyCurrentFlag As FlagType
Sub AccessDocsOrEmail(ByVal NewFlagValue As FlagType)
If NewFLagValue = FlagType.Docs Or FlagType.Email Then
MyCurrentFlag = NewFlagValue 'Will be either Docs or Email, but NOT Web
End If
End Sub
Since enums can occaisionally grow large, you might also use Select Case:
Code:
Public Enum FlagType
Docs = 1
Email = 2
Web = 3
End Enum
Public Class FlagHandler
Dim MyCurrentFlag As FlagType
Sub AccessDocsOrEmail(ByVal NewFlagValue As FlagType)
Select Case NewFlagValue
Case FlagType.Docs
MyCurrentFlag = NewFlagValue
Me.DoSomethingWithDocs 'May or may not depend on the value of MyCurrentFlag - this is just a stupid example!
Case FlagType.Email
MyCurrentFLag = NewFlagValue
Me.DoSomethingWithEmail
Case FlagType.Web
MyCurrentFLag = NewFLagValue
Me.DOSomethingWebLike
Case Else
'Something has gone horribly worng - handle it
End Sub
Anyway, unless I missed something, this might help! The examples above are silly and meaningless, except as demonstrations of using enums and variables.
Good Luck!
-
Jul 22nd, 2010, 10:12 PM
#4
Re: How to get assigned enums with OR?
Follow the CodeBank link in my signature and check out my thread dedicated to this topic.
Here's a direct link:
http://www.vbforums.com/showthread.php?t=502644
-
Jul 23rd, 2010, 03:47 AM
#5
Re: How to get assigned enums with OR?
 Originally Posted by RunsWithScissors
While ThomasJohnsen indicated one option for ACCCESING the value of the variable flags, it seems to me you are overcomplicating things a bit.
I'm afraid there is no straight forward way of representing multiple flags into a single variable with one or more of the flags being turned on or off. While your example is textbook description of enum, it dosen't solve the opening posters problem of needing to assign multiple flagvalues.
For instance the assignment:
Code:
Dim flags as FlagType = FlagType.Docs Or FlagType.Email
(from the first post) would effectively set flags = FlagType.Web (3 = 2 Or 1) using the enum-values you assigned. This would yield some unexpected results, I'm sure.
Regards Tom
-
Jul 23rd, 2010, 04:32 AM
#6
Re: How to get assigned enums with OR?
The correct way is indeed to use bit flags. The enum values should be manually specified and should be double of the previous value. You can start at 0 if that makes sense (usually for a 'None' choice), or at 1. You can also specify the 'Flags' attribute, which might be optional (I'm not sure):
Code:
<Flags()> _
Public Enum Directions
None = 0
Top = 1
Bottom = 2
Left = 4
Right = 8
End Enum
Using this enum, you can specify a direction of 'top-right' by a bitwise OR combination:
Code:
Dim topRight As Direction = Direction.Top Or Direction.Right
You can bring this back to just 'top' by removing the Right using a bitwise AND NOT:
Code:
topRight = topRight And Not Direction.Right
Finally, to figure out if a flag is set, you use the AND operator again:
Code:
If (topRight And Direction.Left) = Direction.Left Then
' Left is set
ElseIf (topRight And Direction.Right) = Direction.Right Then
' Right is set
End If
(The parenthesis are required!)
To understand how this works you just need to visualize the flags as a row of bits. For the combination of Top and Right, the bits look like
Code:
0001 ' Top
1000 ' Right
------- + ' OR
1001 ' Top OR Right
Now, to check if Top Or Right (1001) contains Right, for example, you AND it with the bits for Right, and check if the result is again Right:
Code:
1001 ' Top Or Right
1000 ' Right
------ * ' AND
1000 ' Right ---> YES
This does not work if the values in the enum are not 2^n. For example, if the values were
Code:
Public Enum Directions
None = 0
Top = 1
Bottom = 2
Left = 3
Right = 4
End Enum
Then Left Or Right would be 111 (7), and (Left Or Right) And Top would be
Code:
111 ' Left Or Right
001 ' Top
------ * ' AND
001 ' Top ---> YES
So it would indicate that Top was indeed in the combination, which it isn't!
The point is that there is exactly one '1' for every flag set, which is only true if the values are 2^n. If they aren't, then you get errors like in my example. Left Or Right should only have two flags set (Left and Right) but it has three (111).
-
Jul 23rd, 2010, 07:18 AM
#7
Re: How to get assigned enums with OR?
 Originally Posted by NickThissen
... You can also specify the 'Flags' attribute, which might be optional (I'm not sure)...
The flag attribute is needed for the ToString method to work properly. Without it, you cannot call ToString of the enum if its value is a combination of 2 or more enum values.
Let us have faith that right makes might, and in that faith, let us, to the end, dare to do our duty as we understand it.
- Abraham Lincoln -
-
Jul 23rd, 2010, 07:46 AM
#8
Re: How to get assigned enums with OR?
 Originally Posted by stanav
The flag attribute is needed for the ToString method to work properly. Without it, you cannot call ToString of the enum if its value is a combination of 2 or more enum values.
Oh, so the ToString returns the set values, that's cool.
Anyway, I can remember reading somewhere that the attribute was not required in C#, but that it was in VB (in order for the bitwise flags to work at all), but I'm pretty sure I've used bitwise combinations before without the attribute... in VB. But I could be wrong.
-
Jul 23rd, 2010, 07:49 AM
#9
Re: How to get assigned enums with OR?
I have this code snippet. It is designed for multi-threading
Code:
Class AppStates
<FlagsAttribute()> _
Public Enum _Flag As Integer
No_FlagSet = 0
a = 1 << 0
b = 1 << 1
c = 1 << 2
d = 1 << 3
e = 1 << 4
f = 1 << 5
g = 1 << 6
h = 1 << 7
i = 1 << 8
j = 1 << 9
k = 1 << 10
l = 1 << 11
m = 1 << 12
n = 1 << 13
o = 1 << 14
p = 1 << 15
q = 1 << 16
r = 1 << 17
s = 1 << 18
t = 1 << 19
u = 1 << 20
v = 1 << 21
w = 1 << 22
x = 1 << 23
y = 1 << 24
z = 1 << 25
aa = 1 << 26
bb = 1 << 27
cc = 1 << 28
dd = 1 << 29
ee = 1 << 30
ff = 1 << 31
All_Flag = -1
End Enum
Private _FlagsState As _Flag
Private _FlagsStateString As New System.Text.StringBuilder
Private Lock_Flag As New Object
Public Function GetState(ByVal FlagsToGet As _Flag) As Boolean
'multiple condition checks (_Flags or _Flags or _Flags)
'Return True if any of the conditions are true
Threading.Monitor.Enter(Me.Lock_Flag)
If (Me._FlagsState And FlagsToGet) = _Flag.No_FlagSet _
Then GetState = False _
Else GetState = True
Threading.Monitor.Exit(Me.Lock_Flag)
End Function
Public Sub ClearState(ByVal FlagsToClear As _Flag)
Threading.Monitor.Enter(Me.Lock_Flag)
Me._FlagsState = Me._FlagsState And (_Flag.All_Flag Xor FlagsToClear)
Threading.Monitor.Exit(Me.Lock_Flag)
End Sub
Public Sub SetState(ByVal FlagsToSet As _Flag)
Threading.Monitor.Enter(Me.Lock_Flag)
Me._FlagsState = Me._FlagsState Or FlagsToSet
Threading.Monitor.Exit(Me.Lock_Flag)
End Sub
Public ReadOnly Property StatesAsString(Optional ByVal BinaryString As Boolean = False) _
As String
Get
If Not BinaryString Then
Me._FlagsStateString.Length = 0
Me._FlagsStateString.Append(Me._FlagsState.ToString)
Return Me._FlagsStateString.ToString
Else
Return Me.niceOutput(Me._FlagsState)
End If
End Get
End Property
Public Function niceOutput(ByVal SomeInteger As Integer) As String
Dim s As New System.Text.StringBuilder
s.Append(Convert.ToString(SomeInteger, 2).PadLeft(32, "0"c))
For z As Integer = s.Length - 8 To 8 Step -8
s.Insert(z, " ")
Next
Return s.ToString
End Function
Public Sub AllStatesClear()
Threading.Monitor.Enter(Me.Lock_Flag)
Me._FlagsState = _Flag.No_FlagSet
Threading.Monitor.Exit(Me.Lock_Flag)
End Sub
End Class
-
Jul 23rd, 2010, 08:41 AM
#10
Re: How to get assigned enums with OR?
 Originally Posted by dbasnett
I have this code snippet. It is designed for multi-threading
Code:
Class AppStates
<FlagsAttribute()> _
Public Enum _Flag As Integer
No_FlagSet = 0
a = 1 << 0
b = 1 << 1
c = 1 << 2
d = 1 << 3
e = 1 << 4
f = 1 << 5
g = 1 << 6
h = 1 << 7
i = 1 << 8
j = 1 << 9
k = 1 << 10
l = 1 << 11
m = 1 << 12
n = 1 << 13
o = 1 << 14
p = 1 << 15
q = 1 << 16
r = 1 << 17
s = 1 << 18
t = 1 << 19
u = 1 << 20
v = 1 << 21
w = 1 << 22
x = 1 << 23
y = 1 << 24
z = 1 << 25
aa = 1 << 26
bb = 1 << 27
cc = 1 << 28
dd = 1 << 29
ee = 1 << 30
ff = 1 << 31
All_Flag = -1
End Enum
Private _FlagsState As _Flag
Private _FlagsStateString As New System.Text.StringBuilder
Private Lock_Flag As New Object
Public Function GetState(ByVal FlagsToGet As _Flag) As Boolean
'multiple condition checks (_Flags or _Flags or _Flags)
'Return True if any of the conditions are true
Threading.Monitor.Enter(Me.Lock_Flag)
If (Me._FlagsState And FlagsToGet) = _Flag.No_FlagSet _
Then GetState = False _
Else GetState = True
Threading.Monitor.Exit(Me.Lock_Flag)
End Function
Public Sub ClearState(ByVal FlagsToClear As _Flag)
Threading.Monitor.Enter(Me.Lock_Flag)
Me._FlagsState = Me._FlagsState And (_Flag.All_Flag Xor FlagsToClear)
Threading.Monitor.Exit(Me.Lock_Flag)
End Sub
Public Sub SetState(ByVal FlagsToSet As _Flag)
Threading.Monitor.Enter(Me.Lock_Flag)
Me._FlagsState = Me._FlagsState Or FlagsToSet
Threading.Monitor.Exit(Me.Lock_Flag)
End Sub
Public ReadOnly Property StatesAsString(Optional ByVal BinaryString As Boolean = False) _
As String
Get
If Not BinaryString Then
Me._FlagsStateString.Length = 0
Me._FlagsStateString.Append(Me._FlagsState.ToString)
Return Me._FlagsStateString.ToString
Else
Return Me.niceOutput(Me._FlagsState)
End If
End Get
End Property
Public Function niceOutput(ByVal SomeInteger As Integer) As String
Dim s As New System.Text.StringBuilder
s.Append(Convert.ToString(SomeInteger, 2).PadLeft(32, "0"c))
For z As Integer = s.Length - 8 To 8 Step -8
s.Insert(z, " ")
Next
Return s.ToString
End Function
Public Sub AllStatesClear()
Threading.Monitor.Enter(Me.Lock_Flag)
Me._FlagsState = _Flag.No_FlagSet
Threading.Monitor.Exit(Me.Lock_Flag)
End Sub
End Class
Great, another big block of code with no real explanation of how it works or what it does. I'm sure that will be really useful to the OP
-
Jul 23rd, 2010, 08:59 AM
#11
Re: How to get assigned enums with OR?
Has anyone checked out my CodeBank thread? It actually does do exactly what was asked for in the first post.
-
Jul 23rd, 2010, 10:14 AM
#12
Re: How to get assigned enums with OR?
 Originally Posted by jmcilhinney
Has anyone checked out my CodeBank thread? It actually does do exactly what was asked for in the first post.
*Raises hand* I did! 
I just wanted to explain a bit how and why it works.
-
Jul 24th, 2010, 10:24 AM
#13
Fanatic Member
Re: How to get assigned enums with OR?
 Originally Posted by ThomasJohnsen
I'm afraid there is no straight forward way of representing multiple flags into a single variable with one or more of the flags being turned on or off. While your example is textbook description of enum, it dosen't solve the opening posters problem of needing to assign multiple flagvalues.
For instance the assignment:
Code:
Dim flags as FlagType = FlagType.Docs Or FlagType.Email
(from the first post) would effectively set flags = FlagType.Web (3 = 2 Or 1) using the enum-values you assigned. This would yield some unexpected results, I'm sure.
Regards Tom
I am late getting back to this, apologies for the asynchronous post . . .
Yeah, after reading some of the posts which followed mine, I have figured out that I am out of my depth, since I am not familiar with the whole "bitwise" thing. I know of the concept, but that's it.
This:
Code:
Dim flags as FlagType = FlagType.Docs Or FlagType.Email
Seemed like a just plain bizarre decalartion to me, but I am coming to see that there is more going on here than I thought! From what I can tell, the OR operator seems to work a little differently in this context as compared to:
Code:
If SomeNumericalValue = 1 Or SomeNumericalValue = 5 Then . . .
Because of the concepts in this post, I am now on a mission to learn and understand Bitwise operations. Beginning here, and branching outwards to Google.
This is one of those moments where I get to humbly acknowledge I was barking up the wrong tree. However, the result is that I have learned something. Thanks.
-
Jul 24th, 2010, 10:24 AM
#14
Fanatic Member
Re: How to get assigned enums with OR?
 Originally Posted by jmcilhinney
Has anyone checked out my CodeBank thread? It actually does do exactly what was asked for in the first post.
Yes! Thanks for that!
-
Jul 24th, 2010, 11:12 AM
#15
Re: How to get assigned enums with OR?
 Originally Posted by RunsWithScissors
This:
Code:
Dim flags as FlagType = FlagType.Docs Or FlagType.Email
Seemed like a just plain bizarre decalartion to me, but I am coming to see that there is more going on here than I thought! From what I can tell, the OR operator seems to work a little differently in this context as compared to:
Code:
If SomeNumericalValue = 1 Or SomeNumericalValue = 5 Then . . .
Actually, they do basically the same thing but the first snippet works at the bit level. The second code snippet combines two boolean expressions into a single boolean expression using the Or operator. The result will be True if either of the operands is True and False if they are both False.
As you know, all data is stored in a computer in binary form. Each bit of a binary number is either 1 or 0, which can be thought of as True and False. When you combine two binary values using a bitwise operator, each bit in the result is a combination of the corresponding bits in the operands. If the operator is Or, a bit in the result will be 1 if the corresponding bit in either of the operands is 1 and 0 if they are both 0. Bitwise operations are really just boolean operations on bits. I've provided similar examples before many times but here's one more:
Code:
11110000
10101010
-------- Or
11111010
As you can see, a 1 in either of the operands produces a 1 in the result. The And operator produces a 1 in the result only if both operands contain a 1:
Code:
11110000
10101010
-------- And
10100000
-
Jul 24th, 2010, 11:43 AM
#16
Re: How to get assigned enums with OR?
For Chris 
Code:
Class AppStates
'use to set and clear single / multiple bits (flags)
'assumes user understands bitwise operations. see following link
'http://msdn.microsoft.com/en-us/library/2h9cz2eb%28v=VS.80%29.aspx
<FlagsAttribute()> _
Public Enum _Flag As Integer
No_FlagSet = 0 'do not change
'32 pre-defined flags. 1, 2, 4, 8, 16, etc.
'Change the alhpa (a - ff) to values something more descriptive
a = 1 << 0
b = 1 << 1
c = 1 << 2
d = 1 << 3
e = 1 << 4
f = 1 << 5
g = 1 << 6
h = 1 << 7
i = 1 << 8
j = 1 << 9
k = 1 << 10
l = 1 << 11
m = 1 << 12
n = 1 << 13
o = 1 << 14
p = 1 << 15
q = 1 << 16
r = 1 << 17
s = 1 << 18
t = 1 << 19
u = 1 << 20
v = 1 << 21
w = 1 << 22
x = 1 << 23
y = 1 << 24
z = 1 << 25
aa = 1 << 26
bb = 1 << 27
cc = 1 << 28
dd = 1 << 29
ee = 1 << 30
ff = 1 << 31
'end pre-defined flags
All_Flag = -1 'do not change
End Enum
Private _FlagsState As _Flag = _Flag.No_FlagSet 'flags for this instance
Private _FlagsStateString As New System.Text.StringBuilder
Private Lock_Flag As New Object 'the lock
Public Function GetState(ByVal FlagsToGet As _Flag) As Boolean
'multiple flag checks (_Flags or _Flags or _Flags)
'Return True if any of the conditions are true
'Return False if all of the conditions are false
Threading.Monitor.Enter(Me.Lock_Flag)
If (Me._FlagsState And FlagsToGet) = _Flag.No_FlagSet _
Then GetState = False _
Else GetState = True
Threading.Monitor.Exit(Me.Lock_Flag)
End Function
Public Sub ClearState(ByVal FlagsToClear As _Flag)
'clear one or more flags
Threading.Monitor.Enter(Me.Lock_Flag)
'this
'_Flag.All_Flag Xor FlagsToClear
'creates a mask that is and'ed with the current flag
Me._FlagsState = Me._FlagsState And (_Flag.All_Flag Xor FlagsToClear)
Threading.Monitor.Exit(Me.Lock_Flag)
End Sub
Public Sub SetState(ByVal FlagsToSet As _Flag)
'set one or more flags
Threading.Monitor.Enter(Me.Lock_Flag)
Me._FlagsState = Me._FlagsState Or FlagsToSet
Threading.Monitor.Exit(Me.Lock_Flag)
End Sub
Public ReadOnly Property StatesAsString(Optional ByVal BinaryString As Boolean = False) _
As String
'returns the flags as a string
'if BinaryString is true then return binary representation
Get
If Not BinaryString Then
Me._FlagsStateString.Length = 0 'clear the string builder
Me._FlagsStateString.Append(Me._FlagsState.ToString) 'convert flags to string
Return Me._FlagsStateString.ToString
Else
Return Me.niceOutput(Me._FlagsState) 'convert flags to binary and return that
End If
End Get
End Property
Public Function niceOutput(ByVal SomeInteger As Integer) As String
Dim s As New System.Text.StringBuilder
'convert integer to 32 bits
s.Append(Convert.ToString(SomeInteger, 2).PadLeft(32, "0"c))
'insert a space every 8 bits for clarity
'comment the next three lines out if desired
For z As Integer = s.Length - 8 To 8 Step -8
s.Insert(z, " ")
Next
Return s.ToString
End Function
Public Sub AllStatesClear()
'set all flags to 0
Threading.Monitor.Enter(Me.Lock_Flag)
Me._FlagsState = _Flag.No_FlagSet
Threading.Monitor.Exit(Me.Lock_Flag)
End Sub
End Class
-
Jul 24th, 2010, 11:56 AM
#17
Fanatic Member
Re: How to get assigned enums with OR?
Again, thanks. Your simple example here helps immensely.
I played with this a little in some code, and have found some fascinating things.
THIS is why I post my own understanding, even if I'm not sure! That way, Someone will come along challenge it.
Cool.
-
Jul 24th, 2010, 12:22 PM
#18
Re: How to get assigned enums with OR?
 Originally Posted by RunsWithScissors
Again, thanks. Your simple example here helps immensely.
I played with this a little in some code, and have found some fascinating things.
THIS is why I post my own understanding, even if I'm not sure! That way, Someone will come along challenge it.
Cool. 
JMC does have a way of explaining things. I can't count how many times his posts have helped me.
Here is a reference that may help in your understanding of bitwise operations:
http://msdn.microsoft.com/en-us/libr...=VS.80%29.aspx
@chris - thanks for the rep!
-
Jul 24th, 2010, 12:29 PM
#19
Fanatic Member
Re: How to get assigned enums with OR?
@dbasnett - thanks for the link! I seem to have rep'd you in the recent past, so I can't again just yet.
-
Jul 24th, 2010, 12:43 PM
#20
Re: How to get assigned enums with OR?
 Originally Posted by RunsWithScissors
@dbasnett - thanks for the link! I seem to have rep'd you in the recent past, so I can't again just yet.
I wasn't asking, but thanks just the same.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|