1

I've got this Function:

Public Class QueryStringUtil
    Public Shared Function GetQueryStringValue(Of T As Structure)(ByVal queryStringVariable As String) As T
        Dim queryStringObject As Nullable(Of T) = Nothing
        If queryStringVariable <> Nothing Then
            If HttpContext.Current.Request.QueryString(queryStringVariable) IsNot Nothing Then
                queryStringObject = CTypeDynamic(Of T)(queryStringVariable)
            End If
        End If

        Return queryStringObject
    End Function

End Class

When I try to call it like this:

Dim intTest As Integer = QueryStringUtil.GetQueryStringValue(Of Integer)("stuff")
Dim stringTest As String = QueryStringUtil.GetQueryStringValue(Of String)("stuff")
Dim datetimeTest As DateTime = QueryStringUtil.GetQueryStringValue(Of DateTime)("stuff")

stringTest gives me the error:

'String' does not satisfy the 'Structure' constraint for type parameter 'T'.

I want our other developers to not worry about having to convert a class to a structure or some stuff like that when they call this function. I just want them to be able to put a standard type in the (Of T) and have it work. I don't mind writing in extra calculations to achieve that.

The other problem is I also need the function to be able to return an actual null value, so I kind of need the queryStringObject as Nullable(Of T). Which means I have to have T as Structure otherwise it tells me that won't work. So looks like if I change what T is I need to run some calculation to delcare the var as nullable or not.

EDIT:

I tried overloading this method so that one returns T and one returns Nullable(Of T) like so:

Public Shared Function GetQueryStringValue(Of T As Class)(ByVal queryStringVariable As String) As T
Public Shared Function GetQueryStringValue(Of T As Structure)(ByVal queryStringVariable As String) As Nullable(Of T)

And naturally it's telling me it can't do that since they just differ by return types. Is there anyway to overload this? I really don't want to have two functions.

SventoryMang
  • 10,275
  • 15
  • 70
  • 113

2 Answers2

3

Its because String can't be nullable and isn't a Structure or a value type. It is a reference type.

You should just have some overloads that returns a String and Nullable versions.

Daniel A. White
  • 187,200
  • 47
  • 362
  • 445
  • Right I knew why it was happening, just couldn't figure out around that. How do you overload a generic without changing the parameters? I am trying to and it isn't liking it. It's going to have to take a string either way because that is what the querystring data is stored as. – SventoryMang Jul 22 '11 at 15:20
1

As unhelpful as this may be, AFAIK there's no way to get around it with generics.

Why not just work with Object? Is it a performance issue?

Public Shared Function GetQueryStringValue(ByVal queryStringVariable As String, ByVal t As Type) As Object
    Dim queryStringObject As Object = Nothing
    If queryStringVariable <> Nothing Then
        If HttpContext.Current.Request.QueryString(queryStringVariable) IsNot Nothing Then
            queryStringObject = CTypeDynamic(queryStringVariable, t)
        End If
    End If

    Return queryStringObject
End Function
user541686
  • 205,094
  • 128
  • 528
  • 886
  • You mean (Of T as Object)? Says `Object cannot be used as a type constraint.` – SventoryMang Jul 22 '11 at 15:40
  • @sah302: No I mean with no generics at all, just use Object. Or is there a reason you can't do that? – user541686 Jul 22 '11 at 15:43
  • I am not quite sure what you mean, can you edit it in your answer? No generics and have it's return type by object, then how do I tell it what type to convert it to upon return? – SventoryMang Jul 22 '11 at 15:48
  • @sah302: Not sure, something like this maybe? Use the original thing as `Object` and use a `Type` for the type conversion. Does that work? (If not, is C# or an external DLL an option?) – user541686 Jul 22 '11 at 15:51
  • Lol, no clue what is going on, but the integer and string calls with your function say `'.' expected` (line is `Dim stringTest As String = QueryStringUtil.GetQueryStringValue("stuff", String)`) and the Datetime one says `'DateTime' is a type and cannot be used as expression`. Well this is a class library project in VB, I think you can have both C# and VB in the same project right? If I can write just this class in C# and it's possible, and still be called in VB in another project, sure it's an option! External .dll is not though. – SventoryMang Jul 22 '11 at 15:58
  • @sah302: Oh lol, it's probably because `type` wasn't a valid identifier (not sure though); try it now. Also: No, you can't have both C# in a single *project*, but you can have them in the same *solution*. It would actually still be an external DLL. – user541686 Jul 22 '11 at 16:00
  • nope same thing =/. I guess I really will just have two functions with different names. It seems that's the only thing now, I don't want to really make a whole other project for this one to be done in C#. – SventoryMang Jul 22 '11 at 16:03
  • @sah302: Oh duh! You're *calling* it with a generic argument, which it obviously doesn't take. Pass it `GetType(DateTime)` instead. – user541686 Jul 22 '11 at 16:07
  • Great, that took care of everything by passing in each type as GetType(argument). Resharper is telling me a runtime error could occur but good enough I say! Thanks. – SventoryMang Jul 22 '11 at 16:10
  • I am kind of curious though how it would look in C# ? – SventoryMang Jul 22 '11 at 16:30
  • @Mehrdad let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/1741/discussion-between-sah302-and-mehrdad) – SventoryMang Jul 22 '11 at 16:30
  • 1
    @sah302: Oh don't worry, it would've been ***ugly*** and undocumented (but likely slightly faster) in C#. [See here if you're interested](http://stackoverflow.com/questions/4764573/why-is-typedreference-behind-the-scenes-its-so-fast-and-safe-almost-magical). (I'm at work right now so I can't really chat, sorry!) – user541686 Jul 22 '11 at 16:45