4

I am casting dynamically with generics and have come across a problem when casting from long to int. The problem basically boils down to the following:

While this works:

 long l = 10;
 int i = (int) l;

This does not:

 long l = 10;
 object o = l;
 int i = (int)o;

So the problem is that I have an object as variable of type object but the instance behind is of type long and I want to cast this to an int. What I have found so far is this article: Representation and identity (Eric Lippert).

So what would be valid is this:

 long l = 10;
 object o = l;
 int i = (int)(long)o;

What I have tried is this:

 long l = 10;
 object o = l;
 int i = (int) Convert.ChangeType(o, typeof(long));

But this does not work. Now the question is how can I cast dynamically without System.InvalidCastException?

Currently I have is this (and it does NOT work):

public T Parse<T>(object value){
    return (T) Convert.ChangeType(value, value.GetType());
}

How can I make it work and be able to pass an object of type long with T beeing int.

user1666620
  • 4,800
  • 18
  • 27
Sjoerd222888
  • 3,228
  • 3
  • 31
  • 64
  • 1
    I don't get it. You found a way that works (casting the object to its original type), but it seems like you want to do it in a more convoluted manner? Also, are you not worried about the possible loss of data in going from a 64-bit integer to a 32-bit? – user1666620 Apr 01 '16 at 14:27
  • Can't you just say `return (T)value;` – Christoph K Apr 01 '16 at 14:29
  • @ChristophKn No, it will throw an InvalidCastException. – Sjoerd222888 Apr 01 '16 at 14:30
  • @user1666620 No I am not concerned about the data-loss. (In fact I am working with int values but for some reason receive them as long type values when communicating over signalR websockets. But that is not the scope of the question.) – Sjoerd222888 Apr 01 '16 at 14:32
  • 3
    Surely you want to use `Convert.ChangeType(value, typeof(T))`? Using `value.GetType()` is a no-op. – Lee Apr 01 '16 at 14:34
  • @Lee This is the solution. Thanks! – Sjoerd222888 Apr 01 '16 at 14:37
  • Why store a `long` and cast it back as an `int`? – Jeroen van Langen Apr 01 '16 at 14:45
  • @JeroenvanLangen I receive the value as long type from an in between library. What I showed here is a minimal example. (see my other comments) – Sjoerd222888 Apr 01 '16 at 14:48

3 Answers3

2

Instead of this:

long l = 10;
object o = l;
int i = (int) Convert.ChangeType(o, typeof(long));

Just ask Convert to give you an int, as that's what you want:

long l = 10;
object o = l;
int i = (int) Convert.ChangeType(o, typeof(int));

The Convert class with use the IConvertable interface to do the conversion for you.

Using this approach you can write your Parse function like this:

T Parse<T>(object value)
{
  return (T) Convert.ChangeType(value, typeof(T));
}

And call it like this:

long l = 10;
object o = l;
int i=Parse<int>(o);
Sean
  • 60,939
  • 11
  • 97
  • 136
0

long to int is type casting, when you doing this you are just changing value of one type to another similar type, in some case that may lead to value loss, and compiler knows how to perform so.

object to int is type conversion. you are attempting to change the underlying type. Hence the runtime error.

Have a look at Casting and Type Conversion & Boxing & Unboxing

Parimal Raj
  • 20,189
  • 9
  • 73
  • 110
  • I don't know what the type is so I reference it as an `object` even though the actual instance is of type `long`. The question is about generic casting. – Sjoerd222888 Apr 01 '16 at 14:50
0

How about this

return (T) TypeDescriptor.GetConverter(typeof(T)).ConvertFromString(value.ToString());

It will still fail if your long value is too big for an int so you would still need to deal with that.

Look at this Generic TryParse

Community
  • 1
  • 1
Marc
  • 973
  • 4
  • 13