简体   繁体   中英

What's wrong with my generic method?

the following generic method gives the compile error "Error 13 Value of type 'Distribution' cannot be converted to 't'" :

Public Shared Function CreateObject(Of t)(ByVal ID As Integer) As t

        Dim TType As Type = GetType(t)

        If TType Is GetType(Distribution) Then
            Return CreateDistribution(ID)

        ElseIf TType Is GetType(Accrual) Then
            Return CreateAccrual(ID)

        End If


    End Function

CreateDistribution returns an object of type 'Distribution'. I'm trying to get the method to perform an action based on the type of t supplied and then return an object of type t. What am I doing wrong?

** Edit: I've commented out the entirety of Distribution other than the class declaration and still get the same error.

The compiler can't know ahead of time that the return type of CreateDistribution will match the type t, regardless of your if statement. Does changing the line to this work?

Return CType(CreateDistribution(ID), t)

Same for the second obviously.

You need to upcast to the return values to Object , then downcast to t .

For example:

Return CType(CType(CreateDistribution(ID), Object), t)

The two casts are necessary because the compiler doesn't know that t is Distribution . Therefore, it cannot allow you to cast from Distribution to t (which, as far as the compiler is concerned, might be Integer ). However, once you upcast to Object , the second cast is fine, because Object can by definition be converted to t , no matter what type t is.
Pre-emptive snarky comment: Yes, I'm aware that that isn't true for pointers.

Generic methods are resolved at compile-time, so the compiler needs to know up front what type T it is going to compile the function with. Looks like you're looking to do a return based on runtime checking, in which case rather than a generic you'll want a method that returns an object that all of your possible returns inherit from. The most basic one you could use would be object -- but obviously wherever you call it from you'd have to do some type checking.

I think you're always going to get an error, as at least one of your return statements will have a type mismatch. The compiler is almost certainly not smart enough to work out that only one of them can possibly be executed for a given t

Here is a more generic way to accomplish what you are trying to do:

    Public Function CreateInstance(Of T)(ByVal ParamArray args() As Object) As T
        Dim obj As T

        If args IsNot Nothing AndAlso args.Length > 0 Then
            obj = CType(Activator.CreateInstance(GetType(T), args), T)
        Else
            obj = Activator.CreateInstance(Of T)()
        End If

        Return obj
    End Function

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM