I am using an Enum type with the object of preventing spurious values being used:-
Public Class MyClass1
Public Enum MyEnum As Byte
FIRST
SECOND
End Enum
Private my_var As MyEnum
Public Property MyVar As MyEnum
Get
Return my_var
End Get
Set
my_var = Value
End Set
End Property
End Class
Public Sub MyWorks
Dim my_object As MyClass1 = New MyClass1
my_object.MyVar = 1 ' Compilation Error
my_object.MyVar = 33 ' Compilation Error
If my_object.MyVar = 1 Then ' No Compilation Error
End If
If my_object.MyVar = 27 Then ' No Compilation Error
End If
If my_object.MyVar = 3.141 Then ' No Compilation Error
End If
If my_object.MyVar = "Fred" Then ' Compilation Error
End If
End Sub
(This compiled with Option Strict On; Option Explicit On
.
As I expected, the attempted assignments to the Enumeration property produce compilation errors (
Option Strict On disallows implicit conversions from 'Integer' to 'MyClass.MyEnum'
).
But the first three comparisons do not, where I was rather hoping they would (especially the second and third, which are nonsense). The fourth comparison doesn't compile but the error message seems strange:-
Option Strict On disallows implicit conversions from 'String' to 'Double'
.
Does anyone know how I can force compilation errors to appear for all of these comparisons?
my_object.MyVar = 1 ' Compilation Error
Reason :my_object.MyVar
is of type MyEnum
, and 1 is of type Integer (Byte/UShort/Etc.) So you have a compilation error with Option Strict On
. Use this instead :
my_object.MyVar = MyEnum.SECOND
' .SECUND should mean "1" as FIRST would be "0" by default..
But why ? "1" should be of type Byte since you've explicitly "strong-tiped" your enum..! Well, you can't assign a literal integer (Byte) value anymore to an enum once Option Strict
is On. With Option Strict Off, it works ! But you may wonder why with Option Strict On, the following also works :
Dim MyByteVar As Byte = 1 ' No compilation error
The MyByteVar is of type Byte
, and without any Type Character identifier after the litteral value, the litteral "1" is assumed to be of type Integer
. But because the compiler knows MyByteVar is of type Byte, it tries to convert "1" to a Byte and it works. Not compilation error occurs.
So don't confund the narrowing conversion with the explicit type mismatch. Converting "1" to the type MyEnum wont work with Option Strict On, not because the compiler can't convert 1 to a matching value in the enumeration, but because the compiler shouldn't even try that. The main purpose of explicitly strong types declaration and strict type assignations is to avoid such risks as stated on the MSDN Option Strict Page. AndAlso, on the MSDN Page about Enumerations, you'll have similar statements :
WRONG I'm sorry, I was fooled by another issue I encountered last week.
You just can't make narrowing conversions (Integer -> Byte) with Option Explicit On.
EDIT 2 : ^^ seems I was right after all :/ Well, I'm unsure to be honest, sorry-sorry..
There is no reason to have created Enumerations
, Option Strict
and Option Explicit
if you're okay with Dim my_var As MyEnum = 1
. Those security checks are there to make your code/coding safer, narrowing by the way the amount of liberty to write anything.
If my_object.MyVar = 1 Then
' my_object.MyVar = MyEnum.FIRST = 0 -> Byte (strongly typed)
' 1 -> Integer by default
' Convert my_object.MyVar to Integer (always a widening conversion)
' 0 is different from 1 (Integer to Integer comparison)
' -> FALSE - No compilation error
If my_object.MyVar = 27 Then
' Same as above and will return FALSE
If my_object.MyVar = 3.141
' my_object.MyVar = MyEnum.FIRST = 0 -> Byte (strongly typed)
' 3.141 -> will default to Double (because you didn't used Type Character flag)
' Convert my_object.MyVar to Double (always a widening conversion)
' 0 is different from 3.141 (Double to Double comparison)
' -> FALSE - No compilation error
If you've set the value of my_object.MyVar to MyEnum.SECOND, the following will not produce a compilation error, and will compare to TRUE :
If my_object.MyVar = 1
' my_object.MyVar = MyEnum.SECUND = 1 -> Byte (strongly typed)
' 1 -> will default to Integer
' Convert my_object.MyVar to Integer = 1
' 1 = 1 => TRUE !
The following is pretty much the same as for the Byte assignation thing :
If my_object.MyVar = "Fred" Then '...
With Option Strict On, there is no such conversion from Double to String allowed. This is an obvious type mismatch and Option Strict forbid that. But why Double and not Byte ? Because the Compiler tries one widening after another while attemting to get a type match. Byte -> Integer -> Long -> .. -> Double.
Either you shoud explicitly convert my_object.MyVar
to a String, either explicitly convert "Fred" to a numeric value. The comparison test will always try to take care of required widening conversions (whenever possible) but only the basic widening ones are allowed with Option Strict On
.
So how to make your code fail upon compilation for the first three row of comparison. Well, I don't know. Perhaps it's worth questioning what is allowed with Option Strict and what is not, so I think that's more a philosophic question than a practical one.
=> Should an expression/evaluation that returns a boolean forbid comparison between numbers of different types ?
=> Should basic widening conversions Byte -> Double be forbidden when Option Strict is On ?
I'm sorry, I'm not qualified to answer such questions...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With