首页 > 解决方案 > 如何在 Visual Basic .NET 中支持自定义对象的上下文隐式转换?

问题描述

我想在我的应用程序中使用命名错误代码。这应该确保每个开发人员不会将纯数字错误代码与其他代码混淆,并且还减少了开发人员需要了解错误代码应该代表什么的时间。

比较这个例子:

Function New() As Integer
    Return 0
End Function

用这个例子:

Function New() As Integer
    Return ErrorCodes.ERROR_SUCCESS
End Function

当然,我可以让开发人员编写如下:

Function New() As Integer
    Return 0 ' ERROR_SUCCESS
End Function

但是,当开发人员更新实际返回代码但忘记了注释时,上面的代码会引发一个陷阱。一些开发人员查看实际的返回代码,一些开发人员查看注释。我想减轻这种困惑。

我提出了以下课程(摘录):

Public Class ErrorCodes
    Private msName As String = Nothing
    Private miValue As Integer = 0

    Public Shared ReadOnly ERROR_SUCCESS As ErrorCodes = New ErrorCodes("ERROR_SUCCESS", 0)

    Private Sub New(ByVal psName As String, ByVal piValue As Integer)
        msName = psName
        miValue = piValue
    End Sub

    Public ReadOnly Property [Name] As String
        Get
            Return msName
        End Get
    End Property

    Public ReadOnly Property [Value] As Integer
        Get
            Return miValue
        End Get
    End Property

    Public Overrides Function ToString() As String
        Return String.Format("[{0}]{1}", msName, miValue)
    End Function
End Class

现在我想像ErrorCodes下面的例子一样使用这个类:

Function New() As Integer
    Return ErrorCodes.ERROR_SUCCESS
End Function

正如预期的那样,我将产生一个异常(类型转换),因为我返回的实际值是类的实例ErrorCodes而不是泛型数据类型Integer

正如您在函数中看到的那样,当将类实例分配给类型化变量时ToString(),我让类自动/隐式地将实例化对象转换为通用数据类型。StringString

有没有办法Integer像我一样对通用数据类型做同样的事情ToString()

由于与 Windows XP SP3 的兼容性原因,我使用的是 .NET Framework 4.0。

另一种表达我想要的方式:

Dim stringVariable As String = ErrorCodes.ERROR_SUCCESS ' should be "[0]ERROR_SUCCESS".
Dim integerVariable As Integer = ErrorCodes.ERROR_SUCCESS ' should be 0.

我不想触发隐式转换警告/错误,或者强制开发人员显式地进行类型转换。

标签: vb.netobjectcasting

解决方案


正如 jmcilhinney 指出的那样,这使用了 Enums 和 Description 属性。

这是课程

'requires
'  Imports System.Reflection
'  Imports System.ComponentModel
Public Class ErrorCodes
    Public Enum ErrCode 'these are the error codes
        'note that the codes should be unique
        <Description("Success")> ERROR_SUCCESS = 0
        <Description("Error A")> ERROR_A = 1
    End Enum

    Public Class InfoForErrCode
        Public TheDescription As String
        Public TheValue As Integer
        Public AsString As String
    End Class

    Public Shared Function Info(TheError As ErrCode) As InfoForErrCode
        Dim rv As New InfoForErrCode
        rv.TheDescription = GetDescription(TheError)
        rv.TheValue = TheError
        rv.AsString = TheError.ToString
        Return rv
    End Function

    Private Shared Function GetDescription(TheError As ErrCode) As String
        Dim rv As String = ""
        Dim fi As FieldInfo = TheError.GetType().GetField(TheError.ToString())

        Dim attr() As DescriptionAttribute
        attr = DirectCast(fi.GetCustomAttributes(GetType(DescriptionAttribute),
                                                 False), DescriptionAttribute())

        If attr.Length > 0 Then
            rv = attr(0).Description
        Else
            rv = TheError.ToString()
        End If
        Return rv
    End Function
End Class

这是它的使用方法

    Dim foo As ErrorCodes.ErrCode = ErrorCodes.ErrCode.ERROR_SUCCESS
    Dim inf As ErrorCodes.InfoForErrCode = ErrorCodes.Info(foo)
    Stop 'examine inf
    foo = ErrorCodes.ErrCode.ERROR_A
    inf = ErrorCodes.Info(foo)
    Stop 'examine inf

推荐阅读