|
-
Aug 14th, 2011, 04:11 PM
#1
Thread Starter
Hyperactive Member
[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
-
Aug 14th, 2011, 04:49 PM
#2
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
-
Aug 14th, 2011, 06:31 PM
#3
Thread Starter
Hyperactive Member
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?
-
Aug 15th, 2011, 01:01 AM
#4
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:
Module Module1
Public Enum EventType
Create = 1
Delete = 2
Rename = 3
End Enum
Public Sub EventCheck(ByVal type As EventType, ByVal other_var As Integer)
If type = EventType.Create Then
'Do_this()
ElseIf type = EventType.Delete Then
'Do_this_instead()
End If
End Sub
End Module
Public Class Form1
Private Sub Form1_Load(...)
Dim tempvar as EventType
tempvar = EventType.Delete 'And would these calls work?
EventCheck(tempvar, varname) ' when typed correctly, yes these work
End Sub
End Class
-
Aug 15th, 2011, 01:18 AM
#5
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:
Public MustInherit Class EventType Public Shared ReadOnly Create As EventType = New CreateEventType() Public Shared ReadOnly Delete As EventType = New DeleteEventType() Public Shared ReadOnly Rename As EventType = New RenameEventType() Private Sub New() End Sub Public MustOverride Sub DoCheck() Private Class CreateEventType Inherits EventType Public Overrides Sub DoCheck() 'Do_this() End Sub End Class Private Class DeleteEventType Inherits EventType Public Overrides Sub DoCheck() 'Do_this_instead() End Sub End Class Private Class RenameEventType Inherits EventType Public Overrides Sub DoCheck() 'Do_something_else?() End Sub End Class End Class Module Module1 Public Sub EventCheck(ByVal type As EventType, ByVal other_var As Integer) type.DoCheck() End Sub End Module Public Class Form1 Public Sub Form1_Load(...) Dim tempvar As EventType tempvar = EventType.Delete EventCheck(tempvar, varname) End Sub 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
-
Aug 15th, 2011, 01:39 AM
#6
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.
-
Aug 15th, 2011, 10:49 AM
#7
Thread Starter
Hyperactive Member
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
-
Aug 15th, 2011, 04:03 PM
#8
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.
-
Aug 15th, 2011, 06:38 PM
#9
Re: Proper location for Global Constant?
 Originally Posted by stepdragon
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.
-
Aug 15th, 2011, 06:44 PM
#10
Re: Proper location for Global Constant?
 Originally Posted by Evil_Giraffe
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.)
-
Aug 15th, 2011, 06:49 PM
#11
Re: Proper location for Global Constant?
 Originally Posted by NickThissen
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 )
-
Aug 15th, 2011, 07:15 PM
#12
Thread Starter
Hyperactive Member
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.
-
Aug 16th, 2011, 04:16 AM
#13
Re: Proper location for Global Constant?
 Originally Posted by Evil_Giraffe
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
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|