Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to unbox from object to type it contains, not knowing that type at compile time?

Tags:

c#

unboxing

At the run-time I get boxed instance of some type. How to unbox it to underlying type?

Object obj; String variable = "Some text";  obj = variable // boxing;  // explicit unboxing, because we know the type of variable at compile time.  var x = (String)obj       // Now let's pretend that we don't know the type of underlying object at compile time.   Type desiredType = obj.GetType(); // But we can figure out.  //And now the question.  //How to express something like this:  var y = (desiredType)obj; //Need to get unboxed instance of initial variable here;  
like image 218
Paul Kyrejto Avatar asked Mar 22 '13 07:03

Paul Kyrejto


People also ask

What happens in memory when you box and unbox a value type?

Boxing is the process of converting a value type to the type object or to any interface type implemented by this value type. When the common language runtime (CLR) boxes a value type, it wraps the value inside a System. Object instance and stores it on the managed heap. Unboxing extracts the value type from the object.

Why use boxing and unboxing in c#?

Boxing and unboxing enables a unified view of the type system wherein a value of any type can ultimately be treated as an object. With Boxing and unboxing one can link between value-types and reference-types by allowing any value of a value-type to be converted to and from type object.


2 Answers

If you don't know the type at compile time, then you can't unbox because you have nowhere to put it - all you can do is store it in an object, which is: boxed.

The same also applies to reference-types like string: you can't cast it to the right type if you don't know the type at compile time: you have nowhere to put it.

You can special-case a few types, for example:

if(obj is int) {     int i = (int)obj;     ... } ... 

Another trick that is sometimes (not often) helpful is to switch into generics; then instead of talking in terms of object you are talking in terms of T. This has... limited use though. The easiest way to do that is via dynamic, for example:

dynamic obj = ... Foo(obj); ... Foo<T>(T val) { ... code with T ... } 

you can also add special cases to that appreach:

Foo(string val) { ... code with string ...} Foo(int val) { ... code with int ...} 

However, frankly I suggest it may be better to look hard at what you are trying to do.

like image 169
Marc Gravell Avatar answered Sep 20 '22 14:09

Marc Gravell


Now lets suppose, that real boxing occur:

int v = 5;  object o = v; //boxed   Type type = o.GetType(); //will return typeof(int)  int convertedBack = (int)Convert.ChangeType(o, type);  Console.WriteLine (convertedBack); //prints 5 

Remark, if you substitute:

object convertedBack = Convert.ChangeType(o, type);  Console.WriteLine (convertedBack); //it still prints 5 Console.WriteLine (o); //it even print 5 here 

The reason is that underlying object is still int. I've just used this example to show you, that boxing is irrelevant here. You need to rely on some abstraction in your operations and if you want to cast to int dynamically, what reference type do you wan to use.

like image 21
Ilya Ivanov Avatar answered Sep 19 '22 14:09

Ilya Ivanov