-1

I have a project in Vb.net and windows form application with dotnet framework 3.5. I am using Enum for storing and processing tasks As :

Public Enum TaskStatus
    none = 0
    completed = 2
    executing = 4
    executed = 8
    errors = 16      
    uploaded = 32
    incomplete = 64  
    all =-1
End Enum

Private Function Manage()
    Dim ts As TaskStatus = TaskStatus.none
    '' Task Performed with Error
    ts = TaskStatus.errors Or TaskStatus.executed
    '' Task Uploading
    ts = ts Or TaskStatus.uploaded
    ts = ts Or TaskStatus.completed
    CheckStatus(ts)
End Function

Private Function CheckStatus(ByVal ts As TaskStatus)
    '' Now i have to check for two or More Enums
    '' ts have current values := Error , Executed, Uploaded , Completed

    If ts = (TaskStatus.uploaded Or TaskStatus.errors) Then
        '' It is not working
    End If
    If ts = (TaskStatus.executed Or TaskStatus.uploaded Or TaskStatus.completed) Then
        '' It is not working
    End If
    If ts And (TaskStatus.uploaded Or TaskStatus.executed) Then
       '' Working, But Not Sure is it correct way ?
    End If
    If (ts And TaskStatus.completed) = TaskStatus.completed Then
        '' Completed 
    End If
End Function

Since ts have current values := Error Or Executed Or Uploaded Or Completed.
I can not use HasFlag due to framework 3.5.

How to compare If enum contains two or more specific values in it, as described in code ?

djv
  • 15,168
  • 7
  • 48
  • 72
Admin
  • 173
  • 3
  • 16
  • You could certainly write your own `HasFlag` method to simplify the code. That status Enum is rather odd - it seems to be a combo of the Status *and* the Result. Seems like it should be two (for clarity and ease of use) – Ňɏssa Pøngjǣrdenlarp Mar 31 '17 at 16:40
  • It's not clear what you are trying to check for. I believe that your first two ifs check to see if the value has only those flags set, which is not true. The 3rd if only compiles with `Option Strict Off` since you are trying to treat an enum value as a boolean. The 4th if checks if the completed flag is set without caring about the other flags. You should probably add to your enum, if you don't have it already, although I don't think it changes how the comparisons work. – Mark Mar 31 '17 at 17:06
  • Possible duplicate of [enum combination, correct way - vb.net](http://stackoverflow.com/questions/43138430/enum-combination-correct-way-vb-net) – Blackwood Mar 31 '17 at 17:13
  • Targeting different concept, That Was only to compare Single Enum value in variable. Actually needed code for "If enum contains two or more specific values in it" ? – Admin Mar 31 '17 at 17:16
  • @ProgramAdmin That's the question you asked before. The answer from James Thorpe shows you how to check if two or more flags are set. – Blackwood Mar 31 '17 at 17:38
  • Why did you skip 1 as a value? – djv Mar 31 '17 at 17:41
  • All should not be -1, it should be the sum of all your values. And you shouldn't need to define it. – djv Mar 31 '17 at 17:42
  • @Blackwood, There is 'no' such code defined by the 'James Thorpe' that shows HOW to check if enum contains two flags... those only check for Single value in Enum. – Admin Mar 31 '17 at 18:31

2 Answers2

4

To check for two flags while ignoring any other flags, perhaps something like:

If (ts And (TaskStatus.uploaded Or TaskStatus.errors)) =
        (TaskStatus.uploaded Or TaskStatus.errors) Then
    ' ...
End If

which is pretty ugly. A helper method would make things a bit better:

Function HasFlags(value As TaskStatus, flags As TaskStatus) As Boolean
    Return (value And flags) = flags
End Function

If HasFlags(ts, TaskStatus.uploaded Or TaskStatus.errors) Then
    ' ...
End If

You can pass in as many flags as you want to check for.

Mark
  • 8,140
  • 1
  • 14
  • 29
3

If the completed bit is high, then it is completed. It doesn't matter which other bits are high.

You could complete with errors and have a value of 18 (completed + errors). It's still complete, and completed with errors.

If your program doesn't work with this logic, then you are using status bits incorrectly.

Also

  • I don't see why you would skip 1 in your enum
  • -1 to represent all is silly because all should be the sum of all your enum values

If you had defined your enum like this,

Public Enum TaskStatus
    completed = 1
    executing = 2
    executed = 4
    errors = 8     
    uploaded = 16
End Enum
  • all will now be 31
  • incomplete is when TaskStatus.Complete bit is 0

Here is how you could design it better and an effective usage example

Public Enum TaskStatus
    completed = 1
    executing = 2
    executed = 4
    errors = 8
    uploaded = 16
End Enum

Sub Main()
    CheckStatus(TaskStatus.executing + TaskStatus.uploaded)
    CheckStatus(TaskStatus.completed + TaskStatus.errors)
    CheckStatus(TaskStatus.completed)
    CheckStatus(TaskStatus.completed + TaskStatus.executing + TaskStatus.executed + TaskStatus.errors + TaskStatus.uploaded)
    Console.ReadLine()
End Sub

Private Sub CheckStatus(ByVal ts As TaskStatus)
    Console.WriteLine("TaskStatus value: {0}", ts)
    If ts And TaskStatus.completed Then
        If ts And TaskStatus.errors Then
            Console.WriteLine("completed with errors")
        Else
            Console.WriteLine("completed without errors")
        End If
    Else
        Console.WriteLine("not completed")
        If ts And TaskStatus.executing Then
            Console.WriteLine("still executing")
            If ts And TaskStatus.uploaded Then
                Console.WriteLine("finished uploading")
            Else
                Console.WriteLine("still uploading")
            End If
        End If
    End If
    If ts = 31 Then
        Console.WriteLine("you set all the status bits!")
    End If
    Console.WriteLine()
End Sub

Output with test program:

TaskStatus value: 18
not completed
still executing
finished uploading

TaskStatus value: 9
completed with errors

TaskStatus value: completed
completed without errors

TaskStatus value: 31
completed with errors
you set all the status bits!

Think about why I removed incomplete. Each bit represents a boolean logical state i.e. it can only be one way or another. If you have a bit for completed and incomplete, then you could potentially have an illogical state where completed and incomplete are both high, a value of 66 + any or all other bits in your example (with the exception of all and none - also why I removed those). The state of complete and incomplete is undefined, so why waste the bit?

Executing and executed offer a similar conundrum, as not all combinations make sense, such as executing + executed, i.e. it is still executing but it has finished executing. But other combinations of these states make sense. Look at this:

             |executed: 0             |executed: 1                   |
----------------------------------------------------------------------
executing: 0 |not currently executing |executed, finished executing  |
executing: 1 |currently executing     |executed, still executing ??? |

If you fix the logic of your program, you will find that you don't need both bits. It is just a sign that there are issues elsewhere.

djv
  • 15,168
  • 7
  • 48
  • 72