Link to home
Start Free TrialLog in
Avatar of rocky050371
rocky050371

asked on

Where to put enumerations?

I have an SMTP class which sets the following property

 Public Property SmtpSAuthenticationType() As AuthenticationTypeException.AuthenticationType
        Get
            Return _smtpSAuthenticationType
        End Get
        Set(ByVal value As AuthenticationTypeException.AuthenticationType)
            Try
                If Not [Enum].IsDefined(GetType(AuthenticationTypeException.AuthenticationType), value) Then
                    Throw New AuthenticationTypeException
                End If
                _smtpSAuthenticationType = value
            Catch ex As Exception
                _errors.Add("SMTP Server Authentication Type", ex.Message)
            End Try
        End Set
    End Property

I have defined the enumeration in the exception, should it be in the class instead?
Avatar of rocky050371
rocky050371

ASKER

As an addition to that if I am using a flags enumeration should they be decalred in the same place too
Avatar of kaufmed
This:

If Not [Enum].IsDefined(GetType(AuthenticationTypeException.AuthenticationType), value) Then

Open in new window


doesn't really benefit you. You have defined the type of SmtpSAuthenticationType to be AuthenticationTypeException.AuthenticationType, so anybody using your code is restricted to assigning values of that type--otherwise a compiler error is generated. The only reason I could think to have code like this is if your property were being assigned via reflection, but I believe even then, an error would occur (a runtime error) due to trying to assign an inappropriate value.

I have defined the enumeration in the exception, should it be in the class instead?
I believe MS suggests enums get their own code file, although they seem to have done a good job of creating enums and other classes inside of other classes, themselves! Put your enum wherever it is the most logical. To me, including the enum inside of the AuthenticationTypeException class seems a bit counter-intuitive.
there is a try block around it, surely checking whether the value is defined within the enumeration provides feedback to those who are consuming the business object
or in fact should I set the property to an integer then check it within the assignment?
You're missing what I'm saying. The type of value inside your set will ALWAYS be AuthenticationTypeException.AuthenticationType. The compiler won't allow you to pass in "cat", 1, new Boat(), etc. You always have to assign a value of type AuthenticationTypeException.AuthenticationType to the SmtpSAuthenticationType member. In other words:

Good
obj.SmtpSAuthenticationType = AuthenticationTypeException.AuthenticationType.FirstEnumMember
obj.SmtpSAuthenticationType = DirectCast(1, AuthenticationTypeException.AuthenticationType)

Open in new window


Bad
obj.SmtpSAuthenticationType = "cat"
obj.SmtpSAuthenticationType = 1
obj.SmtpSAuthenticationType = new Boat()

Open in new window



Note, the difference between #2 Bad and #2 Good is that the good version has an explicit cast. This is assuming you don't have Option Strict set to Off.
I appreciate what you are saying, but to cater for any value being passed in is it better then for calling object to treat the public property as an integer then cast it to the enum for internal use?
but to cater for any value being passed in is it better then for calling object to treat the public property as an integer then cast it to the enum for internal use?
If you were to change the type of SmtpSAuthenticationType to int, then you would want the if logic, because int can hold many more values than what you would probably define in your AuthenticationType enum. The benefit of using an enum over an int is that your range of valid values is restricted to only those defined by the enum; if you use an int, then your possible values become -2147483648 to 2147483647, but you enum may only define 1 to 5. This is why you would want a check like what you have--to weed out the other 4294967291 values that don't correspond to a valid enum value. If you keep the enum as the type of your SmtpSAuthenticationType property, then you avoid having to check for these unacceptable values.
but this then  relies on the calling program to know that the public property only accepts a value within the allowed range.

How would you deal with this?

Presumably if I am right in thinking that removing he enum check is also effectively removing the business rule




It looks like I might be eating crow after this conversation  : \

In testing my assertions, it seems that VB is a tad more "forgiving" than C# is, even though we're still playing in .NET land. Passing in a casted value to an a field/property of type enum will still allow you to store the value without error--C# would not allow this. For example:

Module Module1

    Sub Main()
        Dim x As AuthenticationType = 1700

        Console.WriteLine(x.ToString())
        Console.ReadKey()
    End Sub

End Module

Public Enum AuthenticationType
    FirstEnumMember = 1
End Enum

Open in new window


I've only defined one enum member: FirstEnumMember. Its value is 1. However, in my test code, I am casting the value of 1700 to the enum's type. The assignment will succeed, but when the ToString call hits, you will simply see the value 1700 rather than the default of the enum member's name--if you assigned the value of FirstEnumMember to the variable x, the ToString call would print "FirstEnumMember" and not "1".

Based on this test, you are correct in your logic for the property. If you ever switch to C#, you shouldn't need such logic  = )
:-)

I would still be interested to know how you would do it, would you always just force consumers to pass a correct range value in, or would you switch it to an int etc


I would use an enumeration because it associates friendly names with values. It much easier to remember:

Public Enum LampState
    Off = 0
    On = 1
End Enum

than it is to remember:

obj.LampState = 1  ' Lamp is on

Open in new window


especially since Intellisense will pop up and list "Off" and "On" as possible values when using an enumeration.

In reality, enumerations are integer values under the hood anyway, so when using an enum, you are still using an int--you just get a friendly name associated with the value.
Correction to my first example (to make it more in line with the second:

Public Enum LampState
    Off = 0
    On = 1
End Enum

Open in new window


obj.LampState = LampState.Off

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of kaufmed
kaufmed
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial