将通用类型的对象传递给约束泛型方法vb.net

sim*_*005 6 vb.net generics enums

我有以下功能(删除了try-catch):

    Friend Shared Function ConvertOrDefault(Of T As {Structure, IConvertible})(convertFrom As Object, ignoreCase As Boolean) As T
        Dim retVal As T
        If Not GetType(T).IsEnum Then
            Throw New ArgumentException("Type must be enum")
        ElseIf convertFrom Is Nothing OrElse Not TypeOf convertFrom Is String Then
            Return New T
        ElseIf [Enum].TryParse(convertFrom.ToString(), ignoreCase, retVal) Then
            Return retVal
        Else
            Return New T
        End If
End Function
Run Code Online (Sandbox Code Playgroud)

将给定类型转换为枚举(因此约束),如果它是1.

那很好,但是我有另一个方法(下面简化),它执行更一般的转换,如果传入的类型是枚举,我希望它使用该方法:

Friend Shared Function Convert(Of T)(value as Object) As T
    If GetType(T).IsEnum Then
         Return Enums.ConvertOrDefault(Of T)(value, True)
    Else : return DirectCast(value, T)
    End If
End Function
Run Code Online (Sandbox Code Playgroud)

对于Enums.ConvertOrDefault的调用,这会给出错误:

Type argument 'T' does not inherit from or implement the constraint type 'System.IConvertible'
Type argument 'T' does not satisfy the 'Structure' constraint for type parameter 'T'
Run Code Online (Sandbox Code Playgroud)

我怎么能说"没关系,我知道这是一个Enum所以它很好"?

---编辑---

一种(非常丑陋)的方式如下:

Dim type As Type = GetType(T)

If type.IsEnum Then
    Select Case type.Name
        Case "EnumTypeOne"
            Return DirectCast(DirectCast(Enums.ConvertOrDefault(Of EnumTypeOne)(value, True), Object), T)
         ' ...
Run Code Online (Sandbox Code Playgroud)

但这很可怕.当然有一种方法可以概括吗?

- 编辑2:目的 -

我正在从Oracle数据库中读取数据,该数据库将Enums(我有几个)存储为字符串; 以及各种格式存储其他数据(Byte()RAW,TimeSpan作为IntervalDS等).然后我将该Convert函数用作泛型函数,在给定结果的情况下datareader(column),我可以将该对象转换为适当的类型.

所有Oracle.DataAccess.Client.OracleDataReader.Get...函数都采用索引而不是列名; 因为我不能保证列的顺序,并且为了便于阅读,使用列名更有意义 - 但是我必须自己解析输出.

所以我的代码做了类似的事情:

Dim id as Byte() = Convert(dataReader("id_column"))
Dim something as SomeEnum = Convert(dataReader("somethingCol"))
'...
Run Code Online (Sandbox Code Playgroud)

我可以故意调用Enum.ConvertOrDefault而不是Convert在我期待的时候Enum,但这似乎打破了一般方法的原则,我认为这更有意义......并且还允许我在其他环境中重用该方法.

希望有助于澄清一点.

---编辑3 ---

我从评论中尝试了这个想法:

Friend Shared Function Convert(Of T As {New})(value as Object) as T

Friend Shared Function ConvertOrDefault(Of T As{New}) convertFrom As Object, ignoreCase As Boolean) As T
    If Not GetType(T).IsEnum Then
        Throw New ArgumentException("Type must be enum")
    ElseIf convertFrom Is Nothing OrElse Not TypeOf convertFrom Is String Then
        Return New T
    End If
    Try
        Return CType([Enum].Parse(GetType(T), convertFrom.ToString(), ignoreCase), T)
    Catch ex As Exception
    End Try

    ' default
    Return New T
End Function
Run Code Online (Sandbox Code Playgroud)

但是当我Convert为String或Byte()这样的类型调用方法时,这会产生错误

"类型参数'String'必须具有公共无参数实例构造函数,以满足类型参数'T'的'新'约束

TnT*_*nMn 1

有效:D 谢谢!如果您将其写为答案,您可以获得赏金。遗憾的是我们无法回答这个问题——“我怎么能说“没关系,我知道它是一个枚举,所以它没问题”?”,或者,在将 T 传递给另一个方法时,您可以进一步限制 T 吗?

我建议的实施如下所示。作为尝试解释为什么你不能做你想做的事,也许这会有所帮助。由于 inConvert(Of T)T可以表示任何类型,因此编译器在将其传递给更受约束的泛型类型时无法保证类型安全;有CType泛型类型的函数。

我不明白为什么 Enum.TryParse 方法调用结构约束。查看源代码,它仍然检查 Type.IsEnum 属性,因此尝试施加部分约束似乎是多余的。

Friend Shared Function Convert(Of T)(value As Object) As T
   If GetType(T).IsEnum Then
      Return ConvertOrDefault(Of T)(value, True)
   Else
      Return DirectCast(value, T)
   End If
End Function

Friend Shared Function ConvertOrDefault(Of TEnum)(convertFrom As Object, ignoreCase As Boolean) As TEnum
   ' Since this function only excepts Enum types, declaring the return value
   ' will initialize it to zero.
   Dim retVal As TEnum
   Dim typeTEnum As System.Type = GetType(TEnum)
   If typeTEnum.IsEnum Then
      Dim convertFromString As String = TryCast(convertFrom, String)
      If convertFrom IsNot Nothing AndAlso convertFromString IsNot Nothing Then
         Try
            retVal = DirectCast(System.Enum.Parse(typeTEnum, convertFromString), TEnum)
         Catch ex As ArgumentNullException
            ' eat it
         Catch ex As ArgumentException
            ' eat it
         Catch ex As OverflowException
            ' eat it
         End Try
      End If
   Else
      Throw New ArgumentException("Type must be enum")
   End If
   Return retVal
End Function
Run Code Online (Sandbox Code Playgroud)