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的调用,这会给出错误:
Run Code Online (Sandbox Code Playgroud)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'
我怎么能说"没关系,我知道这是一个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'的'新'约束
有效: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)
| 归档时间: |
|
| 查看次数: |
1326 次 |
| 最近记录: |