Problem: InvalidCastException When Casting Object As Generic Type

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • =?Utf-8?B?QkpT?=

    #1

    Problem: InvalidCastException When Casting Object As Generic Type

    I have written a Generic method that takes an object, a type, T, and returns
    a System.Nullable (Of T) depending on whether or not the object IsDBNull.

    It was working fine until I tried to pass a string as the object and my own
    custom Structure as the type, T. Then I received an InvalidCastExce ption.
    This is despite the fact that a CType from a String to my Structure works
    fine. I assume I probably need to implement some interface that
    VisualBasic.Com pilerServices.C onversions.ToGe nericParameter can call. But I
    don't know what that interface might be.

    I have narrowed everything down here to reproduce the error I am
    experiencing. Please note that this code is simplified and doesn't do the
    DBNull checking or the conversion to a System.Nullable (Of T). If the code
    below can be solved, I can work on fixing the more complex code I actually
    have.

    Here is the code to reproduce the error. Just drop into a console application:

    ' no error checking right now, just plain jane simple
    Public Structure FancyInt

    Public Value As Integer

    Public Overloads Shared Narrowing Operator CType(ByVal source As String) As
    FancyInt
    Dim fi As FancyInt
    fi.Value = CInt(source)
    Return fi
    End Operator

    Public Overloads Shared Widening Operator CType(ByVal source As FancyInt)
    As String
    Return source.ToString
    End Operator

    Public Overrides Function ToString() As String
    Return Value.ToString
    End Function

    Sub New(ByVal s As String)
    Value = CInt(s)
    End Sub

    End Structure

    Module Module1

    Sub Main()
    Console.WriteLi ne(New FancyInt("06109 1977")) 'good
    Console.WriteLi ne(CType("06109 1977", Integer)) 'good
    Console.WriteLi ne(CType("06109 1977", FancyInt)) 'good
    Console.WriteLi ne(FancyConvert (Of Integer)("06109 1977"))' good
    Console.WriteLi ne(FancyConvert (Of FancyInt)("0610 91977")) 'bad line 18
    End Sub

    Function FancyConvert(Of T As Structure)(ByVa l o As Object) As T
    Return CType(o, T) ' line 21
    End Function

    End Module

    Here is the console output of the above Sub Main:

    C:\>Test.exe

    61091977
    61091977
    61091977
    61091977
    System.InvalidC astException: Specified cast is not valid.
    at
    Microsoft.Visua lBasic.Compiler Services.Conver sions.ToGeneric Parameter[T](Object Value)
    at Test.Module1.Fa ncyConvert[T](Object o) in
    C:\TestProject\ Module1.vb:line 21
    at Test.Module1.Ma in() in C:\TestProject\ Module1.vb:line 18

    C:\>

    So, what do I need to do to FancyInt so it is successfully cast just like
    the Integer is successfully cast?

    FYI - I also already tried implementing IConvertible on FancyInt as well as
    tried implementing a TypeConverter along with applyng the TypeConverter
    attribute on FancyInt, but no luck with either.

    I must be missing something simple.

    Any help?
  • Kelly Ethridge

    #2
    Re: Problem: InvalidCastExce ption When Casting Object As GenericType



    BJS wrote:
    I have written a Generic method that takes an object, a type, T, and returns
    a System.Nullable (Of T) depending on whether or not the object IsDBNull.
    >
    It was working fine until I tried to pass a string as the object and my own
    custom Structure as the type, T. Then I received an InvalidCastExce ption.
    This is despite the fact that a CType from a String to my Structure works
    fine. I assume I probably need to implement some interface that
    VisualBasic.Com pilerServices.C onversions.ToGe nericParameter can call. But I
    don't know what that interface might be.
    >
    I have narrowed everything down here to reproduce the error I am
    experiencing. Please note that this code is simplified and doesn't do the
    DBNull checking or the conversion to a System.Nullable (Of T). If the code
    below can be solved, I can work on fixing the more complex code I actually
    have.
    >
    Here is the code to reproduce the error. Just drop into a console application:
    >
    ' no error checking right now, just plain jane simple
    Public Structure FancyInt
    >
    Public Value As Integer
    >
    Public Overloads Shared Narrowing Operator CType(ByVal source As String) As
    FancyInt
    Dim fi As FancyInt
    fi.Value = CInt(source)
    Return fi
    End Operator
    >
    Public Overloads Shared Widening Operator CType(ByVal source As FancyInt)
    As String
    Return source.ToString
    End Operator
    >
    Public Overrides Function ToString() As String
    Return Value.ToString
    End Function
    >
    Sub New(ByVal s As String)
    Value = CInt(s)
    End Sub
    >
    End Structure
    >
    Module Module1
    >
    Sub Main()
    Console.WriteLi ne(New FancyInt("06109 1977")) 'good
    Console.WriteLi ne(CType("06109 1977", Integer)) 'good
    Console.WriteLi ne(CType("06109 1977", FancyInt)) 'good
    Console.WriteLi ne(FancyConvert (Of Integer)("06109 1977"))' good
    Console.WriteLi ne(FancyConvert (Of FancyInt)("0610 91977")) 'bad line 18
    End Sub
    >
    Function FancyConvert(Of T As Structure)(ByVa l o As Object) As T
    Return CType(o, T) ' line 21
    End Function
    >
    End Module
    >
    Here is the console output of the above Sub Main:
    >
    C:\>Test.exe
    >
    61091977
    61091977
    61091977
    61091977
    System.InvalidC astException: Specified cast is not valid.
    at
    Microsoft.Visua lBasic.Compiler Services.Conver sions.ToGeneric Parameter[T](Object Value)
    at Test.Module1.Fa ncyConvert[T](Object o) in
    C:\TestProject\ Module1.vb:line 21
    at Test.Module1.Ma in() in C:\TestProject\ Module1.vb:line 18
    >
    C:\>
    >
    So, what do I need to do to FancyInt so it is successfully cast just like
    the Integer is successfully cast?
    >
    FYI - I also already tried implementing IConvertible on FancyInt as well as
    tried implementing a TypeConverter along with applyng the TypeConverter
    attribute on FancyInt, but no luck with either.
    >
    I must be missing something simple.
    >
    Any help?
    Since your FancyConvert method uses Object as the parameter there is no
    conversion routine from type Object to type FancyInt. And from what I
    know, you aren't allowed to define a CType to convert from type Object.
    You would get the same failure using CType directly as well.

    Dim s As Object = "061091977" ' use type Object
    Console.WriteLi ne(CType(s, FancyInt)) ' fails here

    Comment

    Working...