views:

128

answers:

3

I am pulling a 'long' value from Session, using a generic property, and it is crashing.

so I have:

public static T Get<T>(string key)
{
    if(...)
        return (T)System.Web.HttpContext.Current.Session[key];

    ...
}

When debugging, the value is 4, and it crashes.

+4  A: 

Use Convert.ToInt64

Amitabh
+4  A: 

If you insist on keeping your generic method, you can use Convert.ChangeType():

public static T Get<T>(string key)
{
    if (...)
        return 
          (T) Convert.ChangeType(System.Web.HttpContext.Current.Session[key],
                                 typeof(T));

    ...
}

That will allow you to call:

long n = Get<long>("sessionkey");

But be careful: Convert.ChangeType() doesn't work for all conversions.

Philippe Leybaert
what exactly doesn't it work for? So basically a generic getter for values in Session can't be done 'safely' accross all types.
Blankman
If they can be cast from one type to another, Convert.ChangeType() will work. But converting a string to int will not work. Documentation can be found here: http://msdn.microsoft.com/en-us/library/dtb69x08.aspx
Philippe Leybaert
but string to ints work with Convert.ToInt32("23"); i just dont' get this stuff :)
Blankman
Converting "anything" to "anything" using a generic method is not easy. You'll need to perform a lot of steps and checks. If you really want to have that, you could take a look at the open-source "Vici Core" library (http://viciproject.com/wiki/Projects/Core/Home). It includes generic methods that try to convert anything to anything. Your return statement would simply become "return Session[key].Convert<T>()".
Philippe Leybaert
+1  A: 

So, here's where the problem is:

You had a decimal (100m), that got boxed into an object (while in session) and you are trying to unbox it into a long, and this is where the things hit the fan.

The cast operator in .net does two things actually:

object o="string";
string s=(string) o

here the value of the object never changed, it was the same old "string", if was only its reference that changed. However, when I do

double d= 3.7;
long l = (long) x;

I am actually changing the very nature of the thing, the dand l do not have the same representation, one is a double-width floating point with a value of 3.7, and the other is a 64-bit integer with a value of 3.

The .net operator can do both these things, however, it wont do them at the same time, and thats where your problem was...

decimal d=4m;
object o = d;
long l1 = (long)o; //blows up, the runtime error you got
long l2 = (decimal)o; //compile time error
long l3 = (long)(decimal)o; //first we unbox, then we convert - works

BTW, shameless rip of the master (here for more and better explanations)

SWeko