我正在使用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
(这是用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'
。
有谁知道如何强制编译错误出现在所有这些比较中?
答案 0 :(得分:4)
my_object.MyVar = 1 ' Compilation Error
原因:
my_object.MyVar
的类型为MyEnum
,1的类型为Integer(Byte / UShort / Etc。)因此,Option Strict On
存在编译错误。请改用:
my_object.MyVar = MyEnum.SECOND
' .SECUND should mean "1" as FIRST would be "0" by default..
但为什么呢? “1” 应该是Byte类型,因为你明确地“强调”了你的枚举......!好吧,一旦Option Strict
开启,你就不能再将一个字面整数(字节)值 分配给一个枚举。选项严格关闭,它的工作原理!但是您可能想知道为什么使用Option Strict On,以下也可以:
Dim MyByteVar As Byte = 1 ' No compilation error
MyByteVar的类型为Byte
,并且在litteral值之后没有任何Type Character标识符,则假定litteral“1”属于Integer
类型。但是因为编译器知道MyByteVar是Byte类型,它会尝试将“1”转换为字节并且它可以工作。不会发生编译错误。
所以不要将缩小转化与显式类型不匹配混为一谈。将“1”转换为MyEnum类型将无法使用Option Strict On,这不是因为编译器无法将1转换为枚举中的匹配值,而是因为编译器 不应该尝试。明确强类型声明和严格类型分配的主要目的是避免陈述on the MSDN Option Strict Page所述的风险。而且,在MSDN Page about Enumerations上,你会有类似的陈述:
错误对不起,我被上周遇到的另一个问题所迷惑。
您无法使用Option Explicit On缩小转换(Integer - > Byte)。
编辑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
如果您已将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 !
以下几乎与字节分配事项相同:
If my_object.MyVar = "Fred" Then '...
使用Option Strict On时,不允许从Double转换为String。这是明显的类型不匹配,Option Strict禁止这样做。但为什么Double而不是Byte?因为编译器在尝试获得类型匹配时尝试一个接一个地扩展。字节 - >整数 - >长 - > .. - >双
要么显式地将my_object.MyVar
转换为String,要么将“Fred”显式转换为数字值。比较测试将始终尝试处理所需的扩展转换(尽可能),但Option Strict On
仅允许基本扩展转换。
那么如何在编译前三行比较时使代码失败。好吧,我不知道。也许值得质疑Option Strict允许什么,什么不允许,所以我认为这更像是一个哲学问题而不是实际问题。
=>表达式/评估是否应返回布尔值,禁止不同类型的数字之间进行比较? =>应该基本扩大转换字节 - > Option Strict为On时禁止双击?
对不起,我没资格回答这些问题......