Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I get generics to work with return values that require careful casting?

I've got some data access layer code calls a stored proc and returns scalar values of various datatypes. The syntax is ExecuteDecimal, ExecuteString, etc. I want it to be Execute<string> or Execute<decimal>

I try this implementation and I can't compile, unless I'm doing casting using "(T) value", if I try to check the type and call a method to do the casting, no such luck.

UPDATED question Why do I have to convert to object before converting to T?

UPDATED code

internal T Execute<T>(string storedProcName, Hashtable parameters)
{
      //Next lines do compile (thanks to suggestions from answers!)
      if (typeof(T) == typeof(string))
          return (T) (object) ExecuteScalar(storedProcName, parameters).ToString();
      else if (typeof(T) == typeof(int))
          return (T)(object) Convert.ToInt32(ExecuteScalar(storedProcName, parameters));
      //Next line compiles, but not all things boxed in an object can
      //be converted straight to type T (esp db return values that might contain DbNull.Value, etc)
      return (T)ExecuteScalar(storedProcName, parameters);
}
like image 397
MatthewMartin Avatar asked Jun 04 '10 17:06

MatthewMartin


3 Answers

Try this:

var result = ExecuteScalar(storedProcName, parameters);
if(Convert.IsDBNull(result))
    return default(T);
if(result is T) // just unbox
    return (T)result;
else            // convert
    return (T)Convert.ChangeType(result, typeof(T));

Updated: fixed DBNull handling

like image 161
max Avatar answered Oct 24 '22 08:10

max


typeof(T) == typeof(string)

and for null value check against DBNull.Value

overall method:

internal T Execute<T>(string storedProcName, Hashtable parameters)
{
      object res = ExecuteScalar(storedProcName, parameters);
      if (Convert.IsDBNull(res))
         return default(T); //or handle somehow
      return (T)Convert.ChangeType(res, typeof(T));
}
like image 37
Andrey Avatar answered Oct 24 '22 06:10

Andrey


try the 'as' keyword

object o = ExecuteScalar(storedProcName, parameters);
string s;
int i;
// .. more

if ((s = o as string) != null)
{
  return s;
}
if ((i = o as int?) != null) // can't use as for value types, so use nullable
{
  return Convert.ToInt32(o);
}
return o as T;
like image 34
paquetp Avatar answered Oct 24 '22 07:10

paquetp