重载通用约束/将通用类型参数转换为(Non-)ValueType

时间:2018-10-22 12:06:08

标签: .net vb.net generics

我想用泛型类型参数创建一个重载函数,如果泛型类型是值类型与引用类型,则其作用略有不同。想象一下“重载泛型类型约束”。如果传递了ValueType,我想在某些地方使用T?而不是T。我可以想象用不同的方式用代码表达我想要的东西-不幸的是,我尝试的所有内容都不是正确的代码。

  1. 重载,与常规参数一样
    有一个
    Async Function ReturnAsync(Of T As Class)(...) As Task(Of T) 还有一个
    Async Function ReturnAsync(Of T As Structure)(...) As Task(Of T)。这是行不通的,因为编译器告诉我有两个签名相同的定义。

  2. 手动切换并转到其他分支
    我尝试过的内容,包括想要实现的更完整的示例:

    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?很好。

问题

  1. 我是否犯了或多或少的愚蠢错误,阻止了我实现这一目标?
  2. 是否可以将T转换为Integer / T,如果转换不正确会失败吗?我认为类型转换是对泛型类型的错误思考(一个不是类型转换而是实例)?
  3. 还有另一种“第三种”方式,让我这样做吗?
  4. 实现这一点根本不可能吗?

环境

我在Visual Studio 2017的完整.Net Framework 4.5.2上使用VB.Net。如果有一种仅适用于C#/较新的VS / .Net Framework的解决方案,这将是一个遗憾,但我对此很感兴趣

0 个答案:

没有答案