6

I have 3 similar functions, that only change based on numeric type:

<Extension()> _
Public Function ToNullableShort(ByVal str As String) As Short?
    Dim intReturn As Short
    If Short.TryParse(str, intReturn) Then
        Return intReturn
    Else
        Return Nothing
    End If
End Function

<Extension()> _
Public Function ToNullableByte(ByVal str As String) As Byte?
    Dim intReturn As Byte
    If Byte.TryParse(str, intReturn) Then
        Return intReturn
    Else
        Return Nothing
    End If
End Function

<Extension()> _
Public Function ToNullableLong(ByVal str As String) As Long?
    Dim intReturn As Long
    If Long.TryParse(str, intReturn) Then
        Return intReturn
    Else
        Return Nothing
    End If
End Function

I was trying to make a generic function out of this, but couldn't do it. How can I make a generic function that will take a specific T and make it a Nullable(of T)?

Meta-Knight
  • 17,626
  • 1
  • 48
  • 58
Steve Wright
  • 2,481
  • 3
  • 26
  • 35

2 Answers2

10

There's an identical question here (in C#): Convert string to nullable type (int, double, etc...)

Public Function ConvertString(Of T As Structure)(ByVal value As String) As System.Nullable(Of T)
    Try
        Return DirectCast(Convert.ChangeType(value, GetType(T)), T)
    Catch
        Return Nothing
    End Try
End Function
Community
  • 1
  • 1
jjxtra
  • 20,415
  • 16
  • 100
  • 140
  • 1
    It's too bad there isn't a Convert.TryChangeType method, that would save having to eat an exception when the input string is not valid. – jjxtra Jun 19 '09 at 19:39
3

How about:

Public Shared Function Parse(Of T As Structure)(ByVal value As String) As T?
    If String.IsNullOrEmpty(value) Then
        Return Nothing
    End If
    Return New T?(DirectCast(TypeDescriptor.GetConverter(GetType(T)).ConvertFromInvariantString(value), T))
End Function

(note I used reflector to translate that from the C# below)

You could add try/catch around the ConvertFromInvariantString, but to be honest I'd rather have the code throw an exception if I give it something stoopid - leave nulls for the blank case.

The advantage of this is that it works with your own structs, as long as you associate a type-converter with them, which you can do easily (with an attribute or at runtime).

public static T? Parse<T>(string value) where T : struct
{
    if (string.IsNullOrEmpty(value)) return null;
    return (T)TypeDescriptor.GetConverter(typeof(T))
        .ConvertFromInvariantString(value);
}
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900