Results 1 to 11 of 11

Thread: [RESOLVED] Generics Return Type

  1. #1

    Thread Starter
    Fanatic Member clarkgriswald's Avatar
    Join Date
    Feb 2000
    Location
    USA
    Posts
    774

    Resolved [RESOLVED] Generics Return Type

    It's been a minute since I have developed in .NET, but I am a bit puzzled by something and thinking I may be doing something dumb. I have a generic function that can return type T, but I am having trouble with the casting. Here is my function:

    Code:
    Private ReadOnly Property PaddingConverter As TypeConverter = TypeDescriptor.GetConverter(GetType(Padding))
    
    Public Enum MetadataKey
        Margins
        ...
    End Enum
    
    Public Function LoadData(Of T)(key As MetadataKey) As T
    
        Select Case key
            Case MetadataKey.Margins
    
    'get previously saved padding that was stored using PaddingConverter.ConvertToString
                Dim storedMargins = GetPreviouslySavedMargins() 
    
    ' THIS WORKS - CObj was a suggestion found on web (otherwise says value type Padding cannot be converted to type T)
                If String.IsNullOrWhiteSpace(storedMargins) Then Return CType(CObj(Padding.Empty), T) 
    
                Dim bar = CType(PaddingConverter.ConvertFromString(storedMargins), Padding)
    
    ' this throws an Invalid Cast exception (the specified cast is invalid) - note that if I turn Option Strict OFF and just return CObj(bar), it works
                Return CType(CObj(bar), T) 
        End Select
    
    End Function
    I am not sure why CType(CObj(Padding.Empty), T) works, but the latter conversion does not; they are both converting Padding objects, no? I am basically trying to create a generic function that returns a value that may be one or more types (in this case, just trying to get Padding to work).
    Last edited by clarkgriswald; May 28th, 2024 at 06:38 PM.

  2. #2
    PowerPoster PlausiblyDamp's Avatar
    Join Date
    Dec 2016
    Location
    Pontypool, Wales
    Posts
    2,593

    Re: Generics Return Type

    What happens if you remove the calls to CObj? You shouldn't need to convert to Object to be able to perform a CType.

    What is Padding. Empty defined as? There may not be a conversion from a Padding to a T, but if Empty is defined as Nothing or similar that could be converted to a T.

  3. #3
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,535

    Re: Generics Return Type

    What does "THIS FAILS" actually mean? What actually happens?

  4. #4
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,535

    Re: Generics Return Type

    Also, please explain this line:
    Code:
    Dim storedMargins = foo()
    You're using type inference but you're calling a method that we have no access to, so we can't know the type there. I'm guessing Margin but we should have to guess. Also, what's MetadataKey? You haven't explained how the code at issue fails and we can't test the code you posted because it won't compile. Not great.

  5. #5
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    39,222

    Re: Generics Return Type

    Does this make sense as a generic? The function isn't truly generic, as the return is actually fairly specific. After all, the return has to be something that bar can meaningfully be CType'd into, and that isn't just anything, it's Padding (whatever that is). Therefore, the only viable return types is Padding, or something that can be cast to Padding. I would suggest that an interface might be a better approach to this, assuming you have access to Padding and whatever else that bar could viably be. If they all implemented a common interface, then rather than a generic, you could make it a function that returned that interface. It would be both more explicit and more clear. As written, it can't be "whatever" which is what generic usually means.
    My usual boring signature: Nothing

  6. #6

    Thread Starter
    Fanatic Member clarkgriswald's Avatar
    Join Date
    Feb 2000
    Location
    USA
    Posts
    774

    Re: Generics Return Type

    Sorry for the late reply. I didn't realize I left the tab open, so I wasn't getting any email notifications for the thread. In any event, I updated the code example in original post and included some comments as well.

    Quote Originally Posted by PlausiblyDamp View Post
    What happens if you remove the calls to CObj? You shouldn't need to convert to Object to be able to perform a CType.

    What is Padding. Empty defined as? There may not be a conversion from a Padding to a T, but if Empty is defined as Nothing or similar that could be converted to a T.
    I agree and I didn't use CObj at all until I saw multiple threads suggest to use CObj before casting to T. Padding.Empty is just a padding object consisting of all values of 0.

    Quote Originally Posted by jmcilhinney View Post
    Also, please explain this line:
    Code:
    Dim storedMargins = foo()
    You're using type inference but you're calling a method that we have no access to, so we can't know the type there. I'm guessing Margin but we should have to guess. Also, what's MetadataKey? You haven't explained how the code at issue fails and we can't test the code you posted because it won't compile. Not great.
    Sorry for missing detail, see updated code above.

    Quote Originally Posted by Shaggy Hiker View Post
    Does this make sense as a generic? The function isn't truly generic, as the return is actually fairly specific. After all, the return has to be something that bar can meaningfully be CType'd into, and that isn't just anything, it's Padding (whatever that is). Therefore, the only viable return types is Padding, or something that can be cast to Padding. I would suggest that an interface might be a better approach to this, assuming you have access to Padding and whatever else that bar could viably be. If they all implemented a common interface, then rather than a generic, you could make it a function that returned that interface. It would be both more explicit and more clear. As written, it can't be "whatever" which is what generic usually means.
    I think so as this function would return padding, integers, and strings (depending on the enum value passed to the function)

  7. #7
    PowerPoster PlausiblyDamp's Avatar
    Join Date
    Dec 2016
    Location
    Pontypool, Wales
    Posts
    2,593

    Re: Generics Return Type

    If the return type is dependant on a parameter passed in (not sure if I missed that in your posted code) then I am assuming the generic type (and therefore the return type) would need to match.

    Would it not just be easier to have three functions, each with a specific return type instead?

  8. #8

    Thread Starter
    Fanatic Member clarkgriswald's Avatar
    Join Date
    Feb 2000
    Location
    USA
    Posts
    774

    Re: Generics Return Type

    Quote Originally Posted by PlausiblyDamp View Post
    If the return type is dependant on a parameter passed in (not sure if I missed that in your posted code) then I am assuming the generic type (and therefore the return type) would need to match.

    Would it not just be easier to have three functions, each with a specific return type instead?
    The parameter passed in is just the enum key needed to know which property I am looking to load; so the only thing that is generic is the return type. I could use multiple functions, but thought this was a perfect case to use generics. The weird part is, if Option Infer is off, then returning CObj() of the value works as expected.

  9. #9
    PowerPoster PlausiblyDamp's Avatar
    Join Date
    Dec 2016
    Location
    Pontypool, Wales
    Posts
    2,593

    Re: Generics Return Type

    Quote Originally Posted by clarkgriswald View Post
    The parameter passed in is just the enum key needed to know which property I am looking to load; so the only thing that is generic is the return type. I could use multiple functions, but thought this was a perfect case to use generics. The weird part is, if Option Infer is off, then returning CObj() of the value works as expected.
    Do you have option Strict Off as well?

    Returning an Object would allow you to return anything and you are also losing any compile time type checking as well.

  10. #10

    Thread Starter
    Fanatic Member clarkgriswald's Avatar
    Join Date
    Feb 2000
    Location
    USA
    Posts
    774

    Re: Generics Return Type

    Quote Originally Posted by PlausiblyDamp View Post
    Do you have option Strict Off as well?

    Returning an Object would allow you to return anything and you are also losing any compile time type checking as well.
    In my regular project I have both Strict and Infer ON, but in my sandbox app, I have Infer ON and Strict OFF (misspoke earlier)

  11. #11

    Thread Starter
    Fanatic Member clarkgriswald's Avatar
    Join Date
    Feb 2000
    Location
    USA
    Posts
    774

    Re: Generics Return Type

    I figured out the issue and my apologies for a dumb mistake

    The problem was the call site. I had:

    vb.net Code:
    1. dim foo = LoadData(of Padding)(MetadataKey.Margins)

    Which looked correct until I realized that there was another Type called Padding and I needed to be more specific:

    vb.net Code:
    1. dim foo = LoadData(of Windows.Forms.Padding)(MetadataKey.Margins)

    Once I made that change, all worked.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width