Vb.net 如何防止将枚举与整数进行比较?
我使用的枚举类型的目的是防止使用虚假值:-Vb.net 如何防止将枚举与整数进行比较?,vb.net,enums,Vb.net,Enums,我使用的枚举类型的目的是防止使用虚假值:- 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
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
编译
正如我所料,尝试分配枚举属性会产生编译错误(
选项Strict On不允许从“Integer”隐式转换为“MyClass.MyEnum”
)
但是前三个比较没有,我很希望它们会这样(特别是第二个和第三个,都是胡说八道)。第四个比较没有编译,但错误消息似乎很奇怪:-
选项Strict On不允许从“String”隐式转换为“Double”
有人知道我如何强制在所有这些比较中出现编译错误吗
my_object.MyVar = 1 ' Compilation Error
原因:my_object.MyVar
的类型为MyEnum
,而1的类型为Integer(Byte/UShort/Etc),因此您的选项在上出现编译错误。请改用此选项:
my_object.MyVar = MyEnum.SECOND
' .SECUND should mean "1" as FIRST would be "0" by default..
但是为什么?“1”应该是Byte类型,因为您已经显式地“强倾斜”了您的枚举..!好吧,一旦启用了选项Strict
,您就不能再为枚举分配一个文本整型(字节)值。如果禁用了选项Strict,它就可以工作了!但是您可能想知道为什么启用选项Strict,以下内容也可以工作:
Dim MyByteVar As Byte = 1 ' No compilation error
MyByteVar的类型为Byte
,在literal值之后没有任何类型字符标识符,literal“1”被假定为Integer
类型。但是,由于编译器知道MyByteVar的类型为Byte,所以它尝试将“1”转换为Byte,并且它可以工作。。不会发生编译错误
因此,不要混淆缩小转换与显式类型不匹配。转换“1”对于类型MyEnum,不能使用选项Strict On,这不是因为编译器无法将1转换为枚举中的匹配值,而是因为编译器甚至不应该尝试这样做。显式强类型声明和严格类型分配的主要目的是避免上述风险。此外,在e类似声明:
错了对不起,我被上周遇到的另一个问题愚弄了。
如果选项Explicit On,则无法进行缩小转换(整数->字节)。
编辑2:^^看来我毕竟是对的:/嗯,老实说,我不确定,对不起
- 减少因转置或错误键入数字而导致的错误
- 使将来更改值变得容易
- 使代码更易于阅读,这意味着引入错误的可能性更小
- 确保前向兼容性。如果使用枚举,如果将来有人更改与成员名称对应的值,则代码失败的可能性较小
如果您对MyEnum=1Dim 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?因为编译器在尝试获取类型匹配时会一个接一个地尝试加宽。Byte->Integer->Long->Double
或者您应该显式地将my\u object.MyVar
转换为字符串,或者显式地将“Fred”转换为数值。比较测试将始终尝试处理所需的加宽转换(只要可能),但只有基本的加宽转换才允许使用选项Strict On
那么,在编译前三行比较时,如何使代码失败呢?我不知道。也许有必要质疑Option Strict允许什么,不允许什么,所以我认为这更像是一个哲学问题,而不是一个实际问题
=>返回布尔值的表达式/计算是否应禁止不同类型的数字之间的比较?
=>当“严格”选项处于启用状态时,是否应禁止基本加宽转换字节->双字节
很抱歉,我没有资格回答这样的问题…我不这么认为,伙计。正在发生的是一个扩大的转换。字节数据类型扩大到字节、短、UShort、整数、UInteger、Long、ULong、Decimal、Single、Double
。第四个比较的错误消息非常奇怪。MyVar不是Double。还有选项明确的
对于这段代码摘录来说是不必要的。我也没有资格回答哲学问题,但这从来没有阻止过我……我不认为将枚举
转换为整数应该是一种更广泛的转换。我刚刚发现我的一些代码中有一个缺陷,比如Dim x As EnumOne
,然后是如果x=EnumTwo.Value,那么…
。我在比较中不小心使用了错误的Enum
。编译器很高兴地将两边都加宽为整数,并且没有报告警告。我想要一个编译错误!这就是为什么我选择选项Strict On