Setup

I have a class with an overloaded assignment operator

<!-- language: lang-vb -->
Public Class Timestamp

    ReadOnly _value As String

    Public Sub New(value As String)
        Me._value = value
    End Sub

    Public Shared Widening Operator CType(ByVal input As String) As Timestamp
        Return New Timestamp(input)
    End Operator

End Class

This allows both of the following widening conversions to occur:

<!-- language: lang-vb -->
Dim t1 As Timestamp = "1314"
Dim t2 As Timestamp = CType("1314", Timestamp)

So it will happily change from type String into type Timestamp.

Problem

However, if I have a method that takes Timestamp as a generic, the conversion no longer works.
For example, for the following method:

<!-- language: lang-vb -->
Private Function GenericCast(Of T)(input As Object, output As T) As T
    Return CType(input, T)
End Function

If I call it like this:

<!-- language: lang-vb -->
Dim t3 as Timestamp
t3 = GenericCast("1314", t3)

I'll get the following error:

Unable to cast object of type 'System.String' to type 'Timestamp'. Unable to cast object of type 'System.String' to type 'Timestamp'.

But we already know that I definitely can convert between those types.
Why does it it not work with Generics at runtime?

A potential solution is to use CTypeDynamic instead of CType.

Private Function GenericCastV2(Of T)(input As Object, output As T) As T
	output = CTypeDynamic(Of T)(input)
	Return output
End Function

I know this does not answer your "why" question, but it would just be supposition on my part. My gut answer is that it has to do with the decisions that the VB compiler makes in deciding which helper method to call to complete conversion. As a potential clue to the problem, following concept function will not event compile as valid conversion from String for all types would be required.

Private Function GenericCastConcept(Of T)(input As Object, output As T) As T
	output = CType(input.ToString, T)
	Return output
End Function