0

I was wondering if there is any way to access the expected data type within a function similar to an event arg. I am doubtful that this is possible, though it would be an excellent feature.

I frequently work with (old and disorganized)Mysql databases creating interfaces through VB.Net. Often I will have an optional field which contains a NULL value in the database. I am frequently dealing with errors due to NULL and dbnull values in passing data to and from the database.

To complicate things, I often am dealing with unexpected datatypes. I might have an integer zero, a double zero, an empty string, or a string zero.

So I spend a fair amount of code checking that each entry is of the expected type and or converting NULLs to zeros or empty strings depending on the case. I have written a function ncc(null catch convert) to speed up this process.

Public Function ncc(obj As Object, tp As Type) As Object 'Null Catch Convert Function... 

My function works great, but I have to manually set the type every time I call the function. It would be so much easier if it were possible to access the expected type of the expression. Here is an example of what I mean.

Dim table as datatable adapter.fill(table) dim strinfo as string dim intinfo as long strinfo = ncc(table.Rows(0).Item(0),gettype(String)) 'here a string is expected intinfo = ncc(table.Rows(0).Item(0),gettype(Long)) 'here a long is expected 

It would be so much more efficient if it were possible to access the expected type directly from the function.

Something like this would be great:

Public Function ncc(obj As Object, optional tp As Type = nothing) As Object If tp Is Nothing Then tp = gettype(ncc.expectedtype) 

That way I do not have to hard code the type on each line.

strinfo = ncc(table.Rows(0).Item(0)) 
3
  • You have dim intinfo as integer, you call the method passing GetType(Long), then the method returns Object (??) -- Do you already know the Type of these values? If you do, maybe you want something like Public Function ncc(Of T)(obj As Object) As T If obj Is DBNull.Value Or obj Is Nothing Then Return CType(Nothing, T) Return CType(obj, T) End Function, calling it as, e.g., dim someInt = ncc(Of Integer)(table.Rows(0)(0)). If you accept to get Nothing from reference type objects Commented Nov 11, 2022 at 20:01
  • You can use Reflection to get the return type of a method. Commented Nov 12, 2022 at 5:13
  • There isn't any way for a function to tell what it's going to be assigned to. If you want to do something like this, you need to turn it into a Sub so that the target is a parameter to it. You could even make it generic, and type inference would make it so that you wouldn't have to specify the destination type explicitly. Commented Nov 18, 2022 at 15:45

3 Answers 3

2

You can make the ncc function generic to simplify calling it:

Public Function ncc(Of T)(obj As T) As T If DbNull.Value.Equals(obj) Then Return Nothing Return Obj End Function 

This kind of function will be able to in some cases infer the type, but if there's any possibility of null you'll still want to include a type name (because DBNull will be the inferred type for those values). The advantage is not needing to call gettype() and so gaining a small degree of type safety:

strinfo = ncc(Of String)(table.Rows(0).Item(0)) 

But I think this has a small chance to blow up at run time if your argument is not implicitly convertible to the desired type. What you should be doing is adding functions to accept a full row and return a composed type. These functions can exist as static/shared members of the target type:

 Shared Function FromDataRow(IDataRow row) As MyObject 

And you call it for each row like this:

 Dim record As MyObject = MyObject.FromDataRow(table.Rows(i)) 
Sign up to request clarification or add additional context in comments.

Comments

0

But, you problem still exists.

What happens if the column in the database row is null?

then you DO NOT get a data type!

Worse yet? Assume the data column is null, do you want to return null into that variable anyway?

Why not specify a value FOR WHEN its null.

You can use "gettype" on the passed value, but if the data base column is null, then you can't determine the type, and you right back to having to type out the type you want as the 2nd parameter.

You could however, adopt a nz() function (like in VBA/Access).

So, this might be better:

Public Function ncc(obj As Object, Optional nullv As Object = Nothing) As Object If obj Is Nothing OrElse IsDBNull(obj) Then Return nullv End If Return obj End Function 

So, I don't care if the database column is null, or a number, for such numbers, I want 0.

So

 dim MyInt as integer Dim MyDouble As Double MyInt = ncc(rstData.Rows(0).Item("ContactID"), 0) MyDouble = ncc(rstData.Rows(0).Item("ContactID"), 0) dim strAddress as string = "" strAddress = ncc(rstData.Rows(0).Item("Address"), "") 

Since in NEAR ALL cases, you need to deal with the null from the DB, then above not only works for all data types, but also gets you on the fly conversion.

I mean, you CAN declare variables such as integer to allow null values.

eg:

 dim myIntValue as integer? 

But, I not sure above would create more problems than it solves.

So,

Comments

0

You can't get exactly what you want, because a function never has knowledge of how it's going to be used. It's not guaranteed that it will be on the right-hand side of an assignment statement.

If you want to have knowledge of both sides, you either need to be assigning to a custom type (so that you can overload the assignment operator) or you need to use a Sub instead of an assignment.

You could do something like this (untested):

Public Sub Assign(Of T)(ByVal field As Object, ByRef destination As T, Optional ByVal nullDefault As T = Nothing) If TypeOf field Is DBNull Then destination = nullDefault Else destination = CType(field, T) End If End Sub 

I haven't tested this, so I'm not completely certain that the compiler would allow the conversion, but I think it would because field is type Object. Note that this would yield a runtime error if field is not convertible to T.

You could even consider putting on a constraint requiring T to be a value type, though I don't think that would be likely to work because you probably need to handling String which is a reference type (even though it basically acts like a value type).

Because the destination is an argument, you wouldn't ever need to specify the generic type argument, it would be inferred.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.