locked
Is there any 'Mapping' class to replace 'if then else'?

    Question

  • Hello, I wanna do sth by checking the condition. let's say

     

    If request="hello" Then

    Hello( )

    Elseif request="world" Then

    World( )

    Elseif request="goodbye" Then

    Goodbye( )

    Elseif request="kiss" Then

    Kiss( )

    Elseif

    ...

     

    End If

     

    Sub Hello( )

    ...

    End Sub

     

    Sub World( )

    ...

    End Sub

     

    ...


    If I have more requests, say, 20 , then the program may be less efficient.

    Well, maybe we'll use 'switch case'  instead, but yet a 'switch case' seems not much better than 'if then else'.
    Is there any class in vb that provides mapping of request and function, that may make the program better in term of efficiency?

    Thursday, September 20, 2007 10:16 AM

Answers

  • There are many ways you could do this, each with advantages and disadvantages.  The Select/Case method is what I'd recommend for most cases with a relatively small number of possibilities, mostly for readability's sake, and where performance is not a big concern.

     

    However, my guess is that performance is not going to be much of an issue for you.  If the user is interacting with the program directly, inputting commands, then the user won't be able to notice any difference in performance, even when comparing 20 strings.  If the user is not the bottleneck, and you're doing this kind of processing over and over again, then the performance of the look-ups might be important, you'll really have to decide whether that's really the case.

     

    If performance is truly a concern, note that CallByName() is very, very slow (it uses "reflection").  One way to do this with better performance would be to use the Dictionary class, which uses a hashtable internally, which will be much faster than 20 string comparisons.  You could create a dictionary that maps your request strings to the addresses of different functions.  Look up the function in the mapping table, and then call it.  E.g.:

     

    Code Snippet

    'This describes the signature all of our functions have to have. A delegate is

    ' a pointer to a function.

    Private Delegate Sub RequestDelegate()

    'The mapping dictionary - if you want case-sensitive comparison, remove the

    ' StringComparer.OrdinalIgnoreCase argument.

    Dim mapRequestToFunction As New Dictionary(Of String, RequestDelegate)(StringComparer.OrdinalIgnoreCase)

    Sub Main()

    InitializeMap()

    Dim request As String = "hello"

    Dim delegateToCall As RequestDelegate = Nothing

    'Look in the dictionary for the request

    If mapRequestToFunction.TryGetValue(request, delegateToCall) Then

    'Found - invoke the delegate. This will cause the function to get

    ' called.

    delegateToCall.Invoke()

    Else

    'Not found.

    MsgBox("Unrecognized")

    End If

    End Sub

    Private Sub InitializeMap()

    'Initialize the mapping table - only needs to be done once

    mapRequestToFunction.Add("hello", AddressOf Hello)

    mapRequestToFunction.Add("world", AddressOf Hello)

    End Sub

    Private Sub Hello()

    MsgBox("hello")

    End Sub

    Private Sub World()

    MsgBox("World")

    End Sub

     

     

    Good luck.

    Thursday, September 20, 2007 11:28 PM

All replies

  • Hi,

     

    SELECT CASE - END SELECT as below.

    You would put the code block in a button click event SUB or other routine usually.

     

     

     

    Regards,

     

    John.

     

     

    Code Snippet

     

    Public Class Form1

    Dim request As String = ""

     

    'The next highlighted line should be one line of code in your code window.>>>>

     

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

     

     

    Select Case request.ToLower

    Case Is = "kiss"

    Call kiss()

    Case Is = "hello"

    Call hello()

    Case Is = "goodbye"

    Call goodbye()

    Case Else

    MessageBox.Show("Request not recognised, sorry.")

    End Select

     

    End Sub

     

     

     

     

    Sub kiss()

     

    End Sub

     

     

     

    Sub hello()

     

    End Sub

     

     

     

    Sub goodbye()

     

    End Sub

     

    End Class

     

     

     

    Thursday, September 20, 2007 10:29 AM
  • Code Snippet

    CallByName(Me, request, CallType.Method)

     

     

    Thursday, September 20, 2007 10:50 AM
  • Replace

     

    Code Snippet

    If request="hello" Then

    Hello( )

    Elseif request="world" Then

    World( )

    Elseif request="goodbye" Then

    Goodbye( )

    Elseif request="kiss" Then

    Kiss( )

    End if

     

     

     

    For

     

    Code Snippet

    Try

     CallByName(Me, cstr(request), CallType.Method, Nothing)

    Catch ex As Exception

     MsgBox("The method " + cstr(request) + "not exist.")

    End Try

     

    If request is string remove cstr()

     

    Regards,

       Alvarez Arigos Roberto Miguel  

    Thursday, September 20, 2007 4:21 PM
  • There are many ways you could do this, each with advantages and disadvantages.  The Select/Case method is what I'd recommend for most cases with a relatively small number of possibilities, mostly for readability's sake, and where performance is not a big concern.

     

    However, my guess is that performance is not going to be much of an issue for you.  If the user is interacting with the program directly, inputting commands, then the user won't be able to notice any difference in performance, even when comparing 20 strings.  If the user is not the bottleneck, and you're doing this kind of processing over and over again, then the performance of the look-ups might be important, you'll really have to decide whether that's really the case.

     

    If performance is truly a concern, note that CallByName() is very, very slow (it uses "reflection").  One way to do this with better performance would be to use the Dictionary class, which uses a hashtable internally, which will be much faster than 20 string comparisons.  You could create a dictionary that maps your request strings to the addresses of different functions.  Look up the function in the mapping table, and then call it.  E.g.:

     

    Code Snippet

    'This describes the signature all of our functions have to have. A delegate is

    ' a pointer to a function.

    Private Delegate Sub RequestDelegate()

    'The mapping dictionary - if you want case-sensitive comparison, remove the

    ' StringComparer.OrdinalIgnoreCase argument.

    Dim mapRequestToFunction As New Dictionary(Of String, RequestDelegate)(StringComparer.OrdinalIgnoreCase)

    Sub Main()

    InitializeMap()

    Dim request As String = "hello"

    Dim delegateToCall As RequestDelegate = Nothing

    'Look in the dictionary for the request

    If mapRequestToFunction.TryGetValue(request, delegateToCall) Then

    'Found - invoke the delegate. This will cause the function to get

    ' called.

    delegateToCall.Invoke()

    Else

    'Not found.

    MsgBox("Unrecognized")

    End If

    End Sub

    Private Sub InitializeMap()

    'Initialize the mapping table - only needs to be done once

    mapRequestToFunction.Add("hello", AddressOf Hello)

    mapRequestToFunction.Add("world", AddressOf Hello)

    End Sub

    Private Sub Hello()

    MsgBox("hello")

    End Sub

    Private Sub World()

    MsgBox("World")

    End Sub

     

     

    Good luck.

    Thursday, September 20, 2007 11:28 PM
  • oh yeah, I think the Dictionary class will be the approach.

    The string looking up is frequently executed in the program

    Friday, September 21, 2007 4:19 AM
  • This is really good stuff!

     

    Can this logic be used the same way in C#? If so, what is the syntax for CallByName() and AddressOf ?

     

    Thanks!

    Cordially,

    Agustin Garzon

     

     

    Friday, September 21, 2007 9:43 AM