如何阻止Enum与Integer的比较?

时间:2014-10-16 10:33:05

标签: vb.net enums

我正在使用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'

有谁知道如何强制编译错误出现在所有这些比较中?

1 个答案:

答案 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 StrictOption ExplicitDim 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时禁止双击?

对不起,我没资格回答这些问题......