1

I have a generic Class I'm using to hold information loaded from a database.

I have a method which takes a DataRow as an argument, uses the object's known column name and extracts the data from the DataRow, such that:

Dim loadData As T = CType(myDataRow("myColumnName"), T))

works as my default assignment in most cases.

Unfortunately, due to some horrifying design constraints, some of my columns may be null, and may also be taken from enumerations.

This means that when <T> is Nullable(Of SomeEnumeration) the above code does not work because I can't cast 0 directly to SomeEnumeration.Zero.

Is there some way to check whether <T> is Nullable(Of [Enum])? Or some way to write a method which allows Integers to be cast to Nullable(Of [Enum])?

I feel like I'm forgetting something that would allow me to write one of the other of these, but my weak google-fu is turning up nothing.

EDIT: Okay, thanks to dasblinkenlight's answer below, I can detect when this circumstance is occurring, but what I need to do now is to take a type <T> which I know is Nullable(Of SomeClass), get a type reference to SomeClass and then create a new object of type Nullable(Of SomeClass) and assign that to LoadData.

Everything I try falls apart. Any ideas?

EDIT 2:

My solution for getting the value of that enum value was:

Dim baseType As Type = Nullable.GetUnderlyingType(GetType(T))
loadData = [Enum].Parse(baseType, dataRowIn(Me._dataName))

My problem was that I had a lot of difficulty in finding any function which would accept baseType as an actual Type.

[Enum].Parse accepted baseType as a parameter, I knew baseType was an [Enum] type because of dasblinkenlight's code, so I was, in this instance, able to code a solution. It's a solution which is very specific to my problem (i.e., T is Nullable(of SomeEnumeration)), but it's a solution nonetheless.

Frosty840
  • 7,965
  • 12
  • 50
  • 86

2 Answers2

2

Assuming myDataRow("myColumnName") returns Object, and that object will be Nullable(Of SomeEnumeration) you can have;

Sub Main
    Dim items(2) As Object
    items(0) = DayOfWeek.Monday
    items(1) = Nothing

    Test (items(0))
    Test (items(1))
End Sub

Sub Test (value As Object)
    Dim typedValue = CType(value, DayOfWeek?)
    Dim notNullValue As DayOfWeek = If(typedValue, DayOfWeek.Sunday)

    Console.WriteLine ("Nullable = {0:g}, NotNull = {1:g}", typedValue, notNullValue)
End Sub

Assuming myDataRow("myColumnName") returns Object and that object will be Nullable(Of Integer) you can have;

Sub Main
    Dim items(2) As Object
    items(0) = 1
    items(1) = Nothing

    Test (items(0))
    Test (items(1))
End Sub

Sub Test (value As Object)
    Dim intValue = CType(value, Integer?)
    Dim typedValue = CType(intValue, DayOfWeek?)
    Dim notNullValue As DayOfWeek = If(typedValue, DayOfWeek.Sunday)

    Console.WriteLine ("Nullable = {0:g}, NotNull = {1:g}", typedValue, notNullValue)
End Sub

The reason this works and a straight cast from Object to Nullable(Of DayOfWeek) fails is because there is no type conversion from Object to DayOfWeek but there is however, a type conversion from Integer to DayOfWeek, so we must first cast to the actual type (Integer) then to the enumeration type.

You will get the same error if you try to cast an Object that is an Integer straight to a Short because there is no type conversion from Object to Short. Where as casting to Integer then to Short will work.

Dim x As Integer = 5

' Fails
CType(x, Short)

'Works
CType(CType(x, Integer), Short)

The key difference being that CType(someInteger, Short) or CType(someInteger, DayOfWeek) are not actually casting, instead it is using an explicit conversion. It just so happens the same syntax/keywords are used for both casting and explicit conversions.

Chris Chilvers
  • 6,429
  • 3
  • 32
  • 53
1

I am not very good at VB syntax, but you know that something is Nullable(Of [Enum]) when this condition is true:

GetType(T).IsGenericType AndAlso
GetType(T).GetGenericTypeDefinition() = GetType(Nullable(Of)) AndAlso
GetType(T).GetGenericArguments()(0).IsEnum

Edit: corrected syntax (once again)

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • It might be because I'm using Devexpress' "CodeRush Express" addon, but pasting that code makes Visual Studio crash... – Frosty840 Dec 14 '11 at 13:45
  • I've uninstalled CodeRush Express (no Disable option, stupidly) and it seems to be the "IsGeneric" method which is doing it. It doesn't seem to exist in VB, and that might be what's killing the IDE. GetType(T).IsGenericType doesn't cause a crash, though. – Frosty840 Dec 14 '11 at 13:56
  • @Frosty840 You are correct, it should be `IsGenericType`. Does the condition work for you? – Sergey Kalinichenko Dec 14 '11 at 14:00
  • The third line is also causing the IDE to crash. The second line is causing no problems so far. I should note that I'm not running the code. Just writing it out is causing the crash. Very oddd. – Frosty840 Dec 14 '11 at 14:10
  • I *think* the method on the third line should be `GetGenericParameterConstraints`. Do you agree? – Frosty840 Dec 14 '11 at 14:13
  • @Frosty840 It should be `GetGenericArguments`. P.S. I did not realize how dependent I was on my IDE's intellisense!.. – Sergey Kalinichenko Dec 14 '11 at 14:19