类型化泛型参数 [英] Typecasting generic parameters
问题描述
使用以下代码:
Function GetSetting(Of T)(ByVal SettingName As String, ByRef DefaultVal As T) As T
Return If(Configuration.ContainsKey(SettingName), CType(Configuration(SettingName), T), DefaultVal)
End Function
产生以下错误:
Value of type 'String' cannot be converted to 'T'.
我可以指定在任何情况下,转换都是可能的
Any way I could specify that in all cases, the conversion will indeed be possible (I'm basically getting integers, booleans, doubles and strings).
编辑:现在似乎有三种解决方案:
Edit: There seem to be three solutions now:
- 使用AMissico提供的`ValueAs`函数
- 投射到`object`,然后投射`T`
- Using the `ValueAs` function provided by AMissico
- Casting to an `object`, then to `T`, with a check for null values
- Using a `DirectCast` over Convert.ChangeType
?
编辑2:
此代码是否有效?
Edit 2: Would this code work?
Function GetSetting(Of T)(ByVal SettingName As String, Optional ByRef DefaultVal As T = Nothing) As T
Return If(Configuration.ContainsKey(SettingName), ConvertTo(Of T)(Configuration(SettingName)), DefaultVal)
End Function
Function ConvertTo(Of T)(ByVal Str As String) As T
Return If(Str Is Nothing Or Str = "", Nothing, CType(CObj(Str), T))
End Function
编辑3: [AMJ]工作代码
Edit 3: [AMJ] Working Code
Function GetSetting(Of T)(ByVal SettingName As String) As T
Return GetSetting(Of T)(SettingName, Nothing)
End Function
Function GetSetting(Of T)(ByVal SettingName As String, ByVal DefaultVal As T) As T
Dim sValue As String = Configuration(SettingName)
If Len(sValue) = 0 Then
Return DefaultVal
Else
Return CType(CObj(sValue), T)
End If
End Function
测试方法
Quick Test Method
Public Sub DoIt()
Me.Configuration.Add("KeyN", Nothing)
Me.Configuration.Add("KeyE", String.Empty) '""
Me.Configuration.Add("Key1", "99")
Me.Configuration.Add("Key2", "1/1/2000")
Me.Configuration.Add("Key3", "True")
Me.Configuration.Add("Key4", "0")
Dim o As Object 'using object in order to see what type is returned by methods
o = Value(Of Integer)("KeyN", 10) '10
o = Value(Of Integer)("KeyE", 10) '10
o = Value(Of Integer)("Key1", 10) '99
o = Value(Of Date)("KeyN", #11/11/2010#)
o = Value(Of Date)("KeyE", #11/11/2010#)
o = Value(Of Date)("Key2", #11/11/2010#)
o = GetSetting(Of Integer)("KeyN", 10) '10
o = GetSetting(Of Integer)("KeyE", 10) '10
o = GetSetting(Of Integer)("Key1", 10) '99
o = GetSetting(Of Date)("KeyN", #11/11/2010#)
o = GetSetting(Of Date)("KeyE", #11/11/2010#)
o = GetSetting(Of Date)("Key2", #11/11/2010#)
Stop
End Sub
推荐答案
Value(Of T)
和 ValueAs
方法支持nullable-types。我使用Microsoft .NET 2.0源代码作为参考。
The Value(Of T)
and ValueAs
methods support nullable-types. I used Microsoft .NET 2.0 source code as a reference.
这是经过良好测试和生产就绪的代码。
This is well-tested and production ready code.
这些库函数中没有错误处理。调用者负责处理发生的任何转换错误。唯一产生的转换错误是明显的错误,例如尝试将字符串abc转换为 Integer
。
There is no error handling in these "library" functions. It is the responsibility of the caller to handle any conversion errors that occur. The only conversion errors generated are obvious errors, such as trying to convert the string "abc" to Integer
.
Public Sub DoIt()
Dim o As Object
o = Value(Of Integer)("foo", 10)
o = Value(Of DateTime)("xxx", #1/1/2000#)
o = Value(Of Boolean?)("nop", True)
Stop
End Sub
Public Function GatherTag(ByVal tag As String) As String
If tag = "foo" Then
Return "99"
Else
Return String.Empty
End If
End Function
''' <summary>
''' Provides strongly-typed access to the tag values. The method also supports nullable types.
''' </summary>
''' <typeparam name="T">A generic parameter that specifies the return type.</typeparam>
''' <param name="tag">The ExifTool Tag Name,</param>
''' <returns>The value, of type T, of the tag.</returns>
Public Function Value(Of T)(ByVal tag As String, ByVal defaultValue As T) As T
Return DirectCast(ValueAs(GetType(T), tag, defaultValue), T)
End Function
''' <summary>
''' Returns the tag's value as the specified type. The method also supports nullable types.
''' </summary>
''' <param name="type">The type to return the tag value as.</param>
''' <param name="tag">The ExifTool Tag Name,</param>
''' <returns>The value of the tag as the type requested.</returns>
Public Function ValueAs(ByVal type As System.Type, ByVal tag As String, ByVal defaultValue As Object) As Object
Dim oResult As Object = Nothing
Dim oTag As String = GatherTag(tag)
If Len(oTag) = 0 Then
'use specified default value
oResult = defaultValue
Else
'is requested type a generic type?
If type.IsGenericType AndAlso type.GetGenericTypeDefinition Is GetType(Nullable(Of )) Then
Dim oUnderlyingType As Type = Nullable.GetUnderlyingType(type)
Dim oConstructed As Type = type.GetGenericTypeDefinition.MakeGenericType(oUnderlyingType)
Dim oValue As Object
oValue = System.Convert.ChangeType(oTag, oUnderlyingType)
If oValue IsNot Nothing Then
oResult = Activator.CreateInstance(oConstructed, oValue)
End If
Else
'non-generic type
oResult = System.Convert.ChangeType(oTag, type)
End If
End If
Return oResult
End Function
这篇关于类型化泛型参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!