Results 1 to 13 of 13

Thread: [RESOLVED] Proper location for Global Constant?

  1. #1

    Thread Starter
    Hyperactive Member stepdragon's Avatar
    Join Date
    Aug 2011
    Location
    Cincinnati
    Posts
    288

    Resolved [RESOLVED] Proper location for Global Constant?

    Hi I want to make a few global constants in my program for ease of writing. for example

    I have a variable called type, which can be 1-3 depending on type (this is for passing information to a subroutine

    I want to have some global constants like:

    ccreate = 1
    cdelete = 2
    crename = 3

    so that while writing the program I can have easy to read names for keeping track of what's going on.

    for example:
    Code:
    EventCheck(ccreate, this_var)
    
    public sub EventCheck(ByVal type as integer, ByVal other_var as integer)
    
         If type = ccreate then
              Do_this()
         Else If type = cdelete then
              Do_this_instead
         End If
    
    end sub
    I just don't know where to define a constant so that it is avaliable in all forms/modules and I don't know the exact syntax for such a definition.

    Thanks

  2. #2
    VB For Fun Edgemeal's Avatar
    Join Date
    Sep 2006
    Location
    WindowFromPoint
    Posts
    4,255

    Re: Proper location for Global Constant?

    If you put the constants into a public Enum and use its name as a parameter in a sub or function you'll then get those as intelisence options too, put the code in a modual and you can use it from any form, sub, etc, something like...


    EventCheck(myglobals.ccreate, this_var)

    Code:
    Module Module1
        Public Enum myglobals
            ccreate = 1
            cdelete = 2
            crename = 3
        End Enum
    
        Public Sub EventCheck(ByVal type As myglobals, ByVal other_var As Integer)
            If type = myglobals.ccreate Then
                'Do_this()
            ElseIf type = myglobals.cdelete Then
                'Do_this_instead()
            End If
        End Sub
    End Module

  3. #3

    Thread Starter
    Hyperactive Member stepdragon's Avatar
    Join Date
    Aug 2011
    Location
    Cincinnati
    Posts
    288

    Re: Proper location for Global Constant?

    Awesome, that's better than what I was looking for. The only question I have is with the:
    Code:
    ByVal type as myglobals
    What I'm asking is, do you have to declare type as myglobals? furthermore, does declaring it that way make "type" a constant? I'm just not fully understanding the usage. I just want to check the contents of "type" against constants, not necessarily have "type" become a constant itself. For example, I may want to change what type is during the subroutine for one reason or another.

    for example:
    Code:
    Module Module1
        Public Enum myglobals
            ccreate = 1
            cdelete = 2
            crename = 3
        End Enum
    
        Public Sub EventCheck(ByVal type As Integer, ByVal other_var As Integer)
            If type = myglobals.ccreate Then     'Would this basically be the same as
                'Do_this()
            ElseIf type = 2 Then                 'This? (for myglobals.cdelete that is)
                'Do_this_instead()
            End If
        End Sub
    End Module
    
    Public Class Form1
        Private Sub Form1_Load(...)
            Dim tempvar as Integer
            tempvar = myglobals.cdelete          'And would these calls work?
            EventCheck(tempvar, varname)         '???
        End Sub
    End Class
    I never really used constants in VB before. I remember from a class in C++ that when you declare a constant, and you compile, the compiler basically goes throughout your code and replaces all of your constants with the numerical equivalent before even compiling. Is that the case with VB or is there some underlying stuff going on which could cause complications?

  4. #4
    PowerPoster Evil_Giraffe's Avatar
    Join Date
    Aug 2002
    Location
    Suffolk, UK
    Posts
    2,555

    Re: Proper location for Global Constant?

    Conceptually it is similar to the C++ model, but in practice it is utterly different There is no replacements of the constants when using enums, for example.

    In the above code, "myglobals" is the name of the enum. "type" is the name of the parameter in the method that contains a "myglobals" value.

    I'm not sure if VB would let you do a straight comparison between an enum and an integer, probably if you don't have Option Strict On. It would be far better to always use the enum name, however. The point of using an enum is to abstract away the actual underlying values used to identify each value of the enum. So, you shouldn't actually care that the "cdelete" value was given an underlying value of "2", it is simply "myglobals.cdelete".

    The benefits would be more obvious with better naming, such as EventType.Create, EventType.Delete and EventType.Rename.

    When passing it around, again, don't pass the underlying integer type (it is possible to extract the integer and convert the integer back to the enum, but it's a kinda horrible thing to do, and breaks the safety of using an enum. Your code should look more like this:

    vbnet Code:
    1. Module Module1
    2.     Public Enum EventType
    3.         Create = 1
    4.         Delete = 2
    5.         Rename = 3
    6.     End Enum
    7.  
    8.     Public Sub EventCheck(ByVal type As EventType, ByVal other_var As Integer)
    9.         If type = EventType.Create Then
    10.             'Do_this()
    11.         ElseIf type = EventType.Delete Then
    12.             'Do_this_instead()
    13.         End If
    14.     End Sub
    15. End Module
    16.  
    17. Public Class Form1
    18.     Private Sub Form1_Load(...)
    19.         Dim tempvar as EventType
    20.         tempvar = EventType.Delete          'And would these calls work?
    21.         EventCheck(tempvar, varname)         ' when typed correctly, yes these work
    22.     End Sub
    23. End Class

  5. #5
    PowerPoster Evil_Giraffe's Avatar
    Join Date
    Aug 2002
    Location
    Suffolk, UK
    Posts
    2,555

    Re: Proper location for Global Constant?

    Actually, having said that, I'm not sure what Form1_Load will do: when dim'ing a value type (which is what an enum is), it gets initialised to a zero value. You don't have a value of the enum that is defined with value 0. That may well throw an error on the enum definition. Hmmm

    The reason that I'm not sure is that I really don't much like enums, so avoid them if at all possible. I would rather create a class for each of the enum types, and if I really needed enum-like access to them, employ the Object Enumeration Pattern, that could look a little like the following:

    vbnet Code:
    1. Public MustInherit Class EventType
    2.     Public Shared ReadOnly Create As EventType = New CreateEventType()
    3.     Public Shared ReadOnly Delete As EventType = New DeleteEventType()
    4.     Public Shared ReadOnly Rename As EventType = New RenameEventType()
    5.  
    6.     Private Sub New()
    7.     End Sub
    8.  
    9.     Public MustOverride Sub DoCheck()
    10.  
    11.     Private Class CreateEventType
    12.         Inherits EventType
    13.  
    14.         Public Overrides Sub DoCheck()
    15.             'Do_this()
    16.         End Sub
    17.     End Class
    18.  
    19.     Private Class DeleteEventType
    20.         Inherits EventType
    21.  
    22.         Public Overrides Sub DoCheck()
    23.             'Do_this_instead()
    24.         End Sub
    25.     End Class
    26.  
    27.     Private Class RenameEventType
    28.         Inherits EventType
    29.  
    30.         Public Overrides Sub DoCheck()
    31.             'Do_something_else?()
    32.         End Sub
    33.     End Class
    34. End Class
    35.  
    36.  
    37. Module Module1
    38.     Public Sub EventCheck(ByVal type As EventType, ByVal other_var As Integer)
    39.         type.DoCheck()
    40.     End Sub
    41. End Module
    42.  
    43. Public Class Form1
    44.     Public Sub Form1_Load(...)
    45.         Dim tempvar As EventType
    46.         tempvar = EventType.Delete
    47.         EventCheck(tempvar, varname)
    48.     End Sub
    49. End Class

    The check code that is relevant to each of the EventTypes is placed in the class that represents that EventType. You keep related concerns together. Salient points of the Object Enum Pattern are having a private constructor for the MustInherit base class, marking the nested Inherited classes as private so they can't be got at directly, and providing readonly shared fields of the instances of the inherited classes.
    Last edited by Evil_Giraffe; Aug 15th, 2011 at 01:34 AM. Reason: correction of code

  6. #6
    PowerPoster Evil_Giraffe's Avatar
    Join Date
    Aug 2002
    Location
    Suffolk, UK
    Posts
    2,555

    Re: Proper location for Global Constant?

    Okay, I tried it out, it's perfectly happy for you to assign a value of 0 to the enum, which then doesn't match any of the enum values. This is part of why I don't like them.

  7. #7

    Thread Starter
    Hyperactive Member stepdragon's Avatar
    Join Date
    Aug 2011
    Location
    Cincinnati
    Posts
    288

    Re: Proper location for Global Constant?

    Ok, that was a bit of reading but I understand where you're coming from...

    That is useful information, but I do have a reason for my question. for example, what if I had saved an integer value to a file, and I load it into my program and use that to compare, or if I just simply had a textbox on the form for the user to unput a number, or along the same lines, used option boxes to set a variable based on which one is selected.

    I know each of these can be done different ways, but for the sake of readable code, I want to just use one global constant across all of the different methods, without throwing in a ton of extra lines of code just to get it to work.

    From what I'm reading (and some quick tests I did) this should "work" fine if I just use it they way I said, but it won't really be "proper" is that correct?

    EDIT: forgot to say thanks, great info

  8. #8
    PowerPoster
    Join Date
    Apr 2007
    Location
    The Netherlands
    Posts
    5,070

    Re: Proper location for Global Constant?

    There is nothing wrong with enums, they are quite common even in the .NET Framework itself. They do have some minor flaws but they should only appear when you're not using them as intended.

    Behind the scenes, an enum value is just an integer. The enum simply helps you avoid 'magic numbers' in your code by 'substituting' the integer with a named value.
    For example, a method might return an error code if something went wrong. You could handle that like this:
    Code:
    Dim error As Integer = Me.RunSomeMethod()
    
    If error = 0 Then 
        MessageBox.Show("Success!")
    ElseIf error = 391 Then
        MessageBox.Show("Connection failed")
    ElseIf error = -593 Then
        MessageBox.Show("Timeout")
    End If
    These values (especially 391 and -593) don't make sense to anyone except if you know what they mean.
    If you use an enum you can replace these values by a proper name:
    Code:
    Public Enum ErrorCode
        Success = 0
        ConnectionFailed = 391
        Timeout = -593
    End Enum
    
    
    Dim error As ErrorCode = Me.RunSomeMethod()
    
    If error = ErrorCode.Success Then 
        MessageBox.Show("Success!")
    ElseIf error = ErrorCode.ConnectionFailed Then
        MessageBox.Show("Connection failed")
    ElseIf error = ErrorCode.Timeout Then
        MessageBox.Show("Timeout")
    End If

    What Evil Giraffe shows you (the object enumeration pattern) is like an extension to the regular enum. An enum 'maps' a name to an integer value. EG's code 'maps' a name to an actual object, which can have methods and properties specific to that object. The usage in the end is similar. If you created an ErrorCode class as in the object enumeration pattern you could do something like this:
    Code:
    Dim error As ErrorCode = Me.RunSomeMethod()
    If error = ErrorCode.Timeout 
       Then MessageBox.Show("Timeout")
    Else
       error.Respond()
    End If
    Respond is now a method on the ErrorCode class, actually on one specific implementation of the abstract ErrorCode class (either SuccessErrorCode, ConnectionFailedErrorCode or TimeoutErrorCode, for example). Each of these implementations has their own implementation for the Respond method, so each could show a different message.



    In short, an enum is a perfectly fine choice for your purpose. Once you see that you might want to put some actual functionality in your enum values (it doesn't seem that way as they are constants you say), then you can take a look at the object enumeration pattern.

  9. #9
    PowerPoster Evil_Giraffe's Avatar
    Join Date
    Aug 2002
    Location
    Suffolk, UK
    Posts
    2,555

    Re: Proper location for Global Constant?

    Quote Originally Posted by stepdragon View Post
    That is useful information, but I do have a reason for my question. for example, what if I had saved an integer value to a file, and I load it into my program and use that to compare, or if I just simply had a textbox on the form for the user to unput a number, or along the same lines, used option boxes to set a variable based on which one is selected.
    In that instance, where the integer value that represents the values in your enum is relevant, then I would suggest instead a named constant would be better than an enum. There's no practical difference between the the two, but having a constant reflects the intent of your code better, in my opinion.

    The enum approach says (to me) "I have values Create, Delete and Rename.".
    The constant approach says "I have a value for Create that is 1, a value for Delete that is 2 and a value for Rename that is 3".


    And as Nick points out, there is nothing "wrong" with enums. My objection to them is definitely a personal choice - I can't see any use for them other than to violate the Tell Don't Ask principle (Instead of checking the value of the enum and taking different action based on that, you simply tell the object to do whatever it is, and the object performs the correct method due to polymorphism - you can see this happening in my example code: the if blocks have disappeared.) and for scattering related concerns. As ever, YMMV, but enums are so much the "default" choice in this situation in .NET that I like to "over-promote" this approach to counter that.

  10. #10
    PowerPoster Evil_Giraffe's Avatar
    Join Date
    Aug 2002
    Location
    Suffolk, UK
    Posts
    2,555

    Re: Proper location for Global Constant?

    Quote Originally Posted by Evil_Giraffe View Post
    In that instance, where the integer value that represents the values in your enum is relevant, then I would suggest instead a named constant would be better than an enum. There's no practical difference between the the two, but having a constant reflects the intent of your code better, in my opinion.
    On second thoughts, maybe not. You want to pass around strongly typed values where possible, and the enum gives you an EventType type to do so, which is far better than an integer parameter.

    The fact that the underlying integer values are important should be conveyed sufficiently by the fact that you have specified them in the enum (where they are not important you wouldn't bother supplying the " = 1" part.)

  11. #11
    PowerPoster Evil_Giraffe's Avatar
    Join Date
    Aug 2002
    Location
    Suffolk, UK
    Posts
    2,555

    Re: Proper location for Global Constant?

    Quote Originally Posted by NickThissen View Post
    If you created an ErrorCode class as in the object enumeration pattern you could do something like this:
    Code:
    Dim error As ErrorCode = Me.RunSomeMethod()
    If error = ErrorCode.Timeout 
       Then MessageBox.Show("Timeout")
    Else
       error.Respond()
    End If
    Respond is now a method on the ErrorCode class, actually on one specific implementation of the abstract ErrorCode class (either SuccessErrorCode, ConnectionFailedErrorCode or TimeoutErrorCode, for example). Each of these implementations has their own implementation for the Respond method, so each could show a different message.
    Yes, except that ErrorCode.Timeout wouldn't need to be special cased of course:

    Code:
    Dim error As ErrorCode = Me.RunSomeMethod()
    error.Respond()
    (And, since it includes a "Success" value, I'd call this SomeMethodResult, perhaps, rather than ErrorCode )

  12. #12

    Thread Starter
    Hyperactive Member stepdragon's Avatar
    Join Date
    Aug 2011
    Location
    Cincinnati
    Posts
    288

    Re: Proper location for Global Constant?

    Alright, I think I have what I need.

    Basically the rest of this thread is just about what is most 'proper'... If I ever went back to school for programming, or did programming for someone else, or with a team, I might pay more attention, but really for the past 10 or so years, the only programming I've done was for my own projects... (other than a few assignments in school, but we never did vb in school, other than the segment on VBA which I taught ^.^ that was in 6th grade general computer class tehe)

    Nobody is gonna see the code for my projects, so I'm going to stick with what works, and is easiest to understand... I never planned on programming as a profession, so I'm ok with that.

    for clarification, I'm going to use an Enum to store constant values, simply because it works and is easy to reference.

  13. #13
    PowerPoster
    Join Date
    Apr 2007
    Location
    The Netherlands
    Posts
    5,070

    Re: Proper location for Global Constant?

    Quote Originally Posted by Evil_Giraffe View Post
    Yes, except that ErrorCode.Timeout wouldn't need to be special cased of course
    Yeah, but I wanted to show that you can still use 'ErrorCode.Timeout', basically the same syntax as an enum, to choose a value or compare another value with (assuming the ErrorCode class overrides the equality methods/operators). That's the nice thing about the object enumeration pattern, it looks like an enum at first sight but is much more powerful when you look further.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width