我正在使用Enum类型,以防止使用虚假值:-
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
Run Code Online (Sandbox Code Playgroud)
(使用编译Option Strict On; Option Explicit On
。
如我所料,尝试对Enumeration属性进行赋值会产生编译错误(
Option Strict On disallows implicit conversions from 'Integer' to 'MyClass.MyEnum'
)。
但是前三个比较不是,我希望它们会在哪里(尤其是第二个和第三个比较,这是胡说八道)。第四个比较未编译,但错误消息似乎很奇怪:
Option Strict On disallows implicit conversions from 'String' to 'Double'
。
有谁知道我可以如何强制所有这些比较出现编译错误?
my_object.MyVar = 1 ' Compilation Error
Run Code Online (Sandbox Code Playgroud)
原因:
my_object.MyVar
是 类型MyEnum
,1 是整数类型(Byte/UShort/Etc.),所以你有一个编译错误Option Strict On
。使用这个代替:
my_object.MyVar = MyEnum.SECOND
' .SECUND should mean "1" as FIRST would be "0" by default..
Run Code Online (Sandbox Code Playgroud)
但为什么 ?“1”应该是 Byte 类型,因为您已经明确“强提示”您的枚举......!嗯,一旦打开,您就不能再将文字整数(字节)值分配给枚举。Option Strict
使用 Option Strict Off,它可以工作!但您可能想知道为什么使用 Option Strict On 时,以下内容也有效:
Dim MyByteVar As Byte = 1 ' No compilation error
Run Code Online (Sandbox Code Playgroud)
MyByteVar 的类型为Byte
,并且在文字值之后没有任何类型字符标识符,则假定文字“1”的类型为Integer
。但是因为编译器知道 MyByteVar 是 Byte 类型,所以它尝试将“1”转换为 Byte并且它可以工作。不会出现编译错误。
因此,不要将缩小转换与显式类型不匹配混淆。将“1”转换为 MyEnum 类型无法与 Option Strict On 一起使用,不是因为编译器无法将 1 转换为枚举中的匹配值,而是因为编译器甚至不应该尝试这样做。显式强类型声明和严格类型分配的主要目的是避免MSDN Option Strict Page 上所述的风险。另外,在有关枚举的 MSDN 页面上,您将看到类似的声明:
错误抱歉,我被上周遇到的另一个问题愚弄了。您只是无法使用 Option Explicit On 进行缩小转换(整数 -> 字节)。
编辑2:^^ 看来我毕竟是对的:/好吧,我不确定说实话,抱歉抱歉..
没有理由创建Enumerations
,Option Strict
如果Option Explicit
你同意的话Dim my_var As MyEnum = 1
。这些安全检查是为了让你的代码/编码更安全,从而缩小编写任何内容的自由度。
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
Run Code Online (Sandbox Code Playgroud)
如果您已将 my_object.MyVar 的值设置为 MyEnum.SECOND,则以下内容不会产生编译错误,并且将与 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 !
Run Code Online (Sandbox Code Playgroud)
以下内容与字节分配几乎相同:
If my_object.MyVar = "Fred" Then '...
Run Code Online (Sandbox Code Playgroud)
使用 Option Strict On 时,不允许从 Double 到 String 的此类转换。这是明显的类型不匹配,Option Strict 禁止这样做。但为什么是 Double 而不是 Byte 呢?因为编译器在尝试获得类型匹配时会尝试进行一次又一次的加宽。字节 -> 整数 -> 长整型 -> .. -> 双精度。
您应该显式转换my_object.MyVar
为字符串,或者显式将“Fred”转换为数值。比较测试将始终尝试处理所需的加宽转换(只要可能),但仅允许基本加宽转换Option Strict On
。
那么如何让你的代码在前三行比较的编译时失败。嗯,我不知道。也许值得质疑 Option Strict 允许什么、不允许什么,所以我认为这更多的是一个哲学问题,而不是一个实际问题。
=> 返回布尔值的表达式/求值是否应该禁止不同类型的数字之间的比较?
=> 当 Option Strict 为 On 时,是否应该禁止基本扩展转换 Byte -> Double ?
抱歉,我没有资格回答这样的问题……