我想用泛型类型参数创建一个重载函数,如果泛型类型是值类型与引用类型,则其作用略有不同。想象一下“重载泛型类型约束”。如果传递了ValueType,我想在某些地方使用T?
而不是T
。我可以想象用不同的方式用代码表达我想要的东西-不幸的是,我尝试的所有内容都不是正确的代码。
重载,与常规参数一样
有一个
Async Function ReturnAsync(Of T As Class)(...) As Task(Of T)
还有一个
Async Function ReturnAsync(Of T As Structure)(...) As Task(Of T)
。这是行不通的,因为编译器告诉我有两个签名相同的定义。
手动切换并转到其他分支
我尝试过的内容,包括想要实现的更完整的示例:
Public Overrides Function ReturnAsync(Of T)(Optional column As String = "Id") As Task(Of T)
If GetType(T).IsValueType Then
Return ReturnAsyncStruct(Of T)(column) ' compiler error
Else
Return ReturnAsyncClass(Of T)(column) ' compiler error
End If
End Function
Private Async Function ReturnAsyncClass(Of T As Class)(Optional column As String = "Id") As Task(Of T)
Dim ret As T = Await UpdateOrSelectAsync(Of T)(column)
If ret Is Nothing Then ret = Await InsertAsync(Of T)(column)
Return ret
End Function
Private Async Function ReturnAsyncStruct(Of T As Structure)(Optional column As String = "Id") As Task(Of T)
Dim ret As T? = Await UpdateOrSelectAsync(Of T?)(column)
If ret Is Nothing Then ret = Await InsertAsync(Of T)(column)
Return ret
End Function
这不起作用,因为第3行和第5行中的调用会导致编译器错误。由于T没有施加任何约束,因此它不能用作带有约束的类型参数,这很有意义。
上下文
总而言之,我想提供一个API,从调用者的角度来看,它对所有类型的行为都完全相同,但是在给定值类型或引用类型的情况下,它需要在内部执行一些稍有不同的操作。请参见上面的示例。
这是我正在编写的Upsert API的摘录。它应该兼容,即与guid(=字符串)ID以及整数ID兼容。现在,当搜索现有实体时,结果可能是NULL
或字符串/整数。如果该实体不存在,则创建它。因此,对于面向公众的API,内部搜索存在的部分需要返回“ T?
({{1}的String
/ String
的{{1}})总是返回Integer?
很好。
问题
Integer
/ T
,如果转换不正确会失败吗?我认为类型转换是对泛型类型的错误思考(一个不是类型转换而是实例)?环境
我在Visual Studio 2017的完整.Net Framework 4.5.2上使用VB.Net。如果有一种仅适用于C#/较新的VS / .Net Framework的解决方案,这将是一个遗憾,但我对此很感兴趣