Why can't an int that's been boxed be directly cast to double?
object o = 12;
double d = (double)o;
That throw an invalid cast exception. Instead it seems it has to first be cast as an int, and then on to double.
object o = 12;
double d = (double)(int)o;
I'm sure the simple answer is "because that's how boxing works" but I'm hoping someone might shed a bit of light here.
Check out this question from earlier today: Why am I getting InvalidCastException?
Unboxing operations only succeed if the target type is exactly the same as the original type that was boxed, so an exception is thrown. This link that John Leidegren provided explains in detail.
If you don't know the original type at compile-time:
object o = 12;
double d = (double)Convert.ChangeType(o, typeof(double));
Related
I'm preparing for an exam and stumbled over a question regarding boxing/unboxing.
I always thought if i box let's say a float like this:
float x = 4.5f;
object o = x;
If a want a value type variable back from o, I will have to unbox it to a float.
float y = (float)o;
This should throw an exception:
int z = int(o);
If I want to cast the value stored in o to an int I will have to unbox it first and cast afterwards like this:
int z = (int)(float)o;
Now the question i stumbled upon:
Suppose you have a method like this:
public static void FloorTemperature(float degrees) {
object degreesRef = degrees;
`xxx`
Console.WriteLine(result);
}
You need to ensure the application does not throw exceptions on invalid conversions. Which code segment should you insert for xxx (I think invalid conversion are invalid cast exceptions):
(a) int result = (int)degreesRef;
(b) int result = (int)(float)degreesRef;
The correct solution is (a), but to me (b) looks correct. So can you please enlighten me? What am I missing?
Kind regards
You aren't missing anything
The answer should be (b) because:
(a) throws an exception since you are trying to cast object to int.
(b) is correct since you first cast it to float then you cast it to int which rounds it but doesn't throw an exception.
This question already has answers here:
Cast object to decimal? (nullable decimal)
(6 answers)
Closed 9 years ago.
I try to cast from Object type to decimal:
Object obj = new Object();
obj = 10;
decimal dec = (decimal)obj;
but in this row decimal dec = (decimal)obj , I get this Exception:
Specified cast is not valid.
Any idea why this unboxing can't be implemented?
Thank you in advance.
which is why you have Convert.ToDecimal() boxing and unboxing can only happen between same types.
10 literal is represented in C# compiler as an System.Int32(correct me if I am wrong people) and hence unboxing of this to a decimal will result in error
You can only unbox a value type to its original type or the nullable equivalent version of that type.
For the reason behind this read this Eric Lippert's
When you write obj = 10;, object has value of type int.
Try this:
Object obj = new Object();
obj = 10M;
decimal dec = (decimal)obj;
or this:
Object obj = new Object();
obj = 10;
decimal dec = (decimal)(int)obj;
You should read Boxing and Unboxing article on msdn.
For the unboxing of value types to succeed at run time, the item being
unboxed must be a reference to an object that was previously created
by boxing an instance of that value type. Attempting to unbox null
causes a NullReferenceException. Attempting to unbox a reference to an
incompatible value type causes an InvalidCastException.
When we convert the data types between primitive data types it is called as data type casting.
But when convert between ValueType and ReferenceType we call it as boxing and unboxing.
Can boxing and unboxing also be called casting?
Boxing is just wrapping a value type in an object hull, essentially. It doesn't actually involve a type conversion as, say, (int)3.14 does. Even though they both use the cast operator.
C# Type System contains three Types , they are Value Types , Reference Types and Pointer Types. C# allows us to convert a Value Type to a Reference Type, and back again to Value Types . The operation of Converting a Value Type to a Reference Type is called Boxing and the reverse operation is called Unboxing.
Boxing
int Val = 1;
Object Obj = Val; //Boxing
The first line we created a Value Type Val and assigned a value to Val. The second line , we created an instance of Object Obj and assign the value of Val to Obj. From the above operation (Object Obj = i ) we saw converting a value of a Value Type into a value of a corresponding Reference Type . These types of operation is called Boxing.
UnBoxing
int Val = 1;
Object Obj = Val; //Boxing
int i = (int)Obj; //Unboxing
The first two line shows how to Box a Value Type . The next line (int i = (int) Obj) shows extracts the Value Type from the Object . That is converting a value of a Reference Type into a value of a Value Type. This operation is called UnBoxing.
Boxing and UnBoxing are computationally expensive processes. When a value type is boxed, an entirely new object must be allocated and constructed , also the cast required for UnBoxing is also expensive computationally
Boxing is the process to converting a value type to the type object and unboxing retriveing the value back http://msdn.microsoft.com/en-us/library/yz2be5wk.aspx
Well as casting is to convert one type to another compatible type
Casting: (it's basically about converting instance of one type into another)
int a = (int) 3.14 // from the example above does casting with loosing precision.
double b = a; // casting again (we may write (double) a - gives the same result).
Boxing: (process of copying value type to the heap)
object c = new MyStruct(); // MyStruct = struct.
object d = 1;
object e = (int) 3.14; // here we have actually casting and then boxing.
Unboxing (copying boxed value type back to the stack):
Button f = (MyStruct) c;
int g = (int) d; // it still unboxing however it looks exactly like the line #1 above.
Hope it helps.
Boxing is basically boxing a value type into a anonymous object which later can be unboxed.
int x = 567;
object y = x; //boxing
int z = (int) y; //z will be 123
int x = 567;
object y = (object)x; //explicit boxing (not necessary)
int z = (int) y; //z will be 123
Boxing/Unboxing should not be confused with type casting as while boxing we are just putting a wrapper around a variable. By doing the type casting you are actually changing the type of the variable or object.
Double x = 3.14444;
Integer y = (Integer)x; //(type cast or static cast in c++) changing the type and loosing the original value too in this case.
int x = 567;
object y = (object)x; //explicit boxing (not necessary)
float z = (float) y; //another example of type casting while unboxing
Every non-nullable value type has an associated heap-object type with identical members. Boxing a value type storage location creates a new heap-type instance and copies all the fields from the value-type storage location to the corresponding fields of the new instance. Unboxing a value type copies all the fields from an instance of its corresponding heap-object type to the corresponding fields of a value-type storage location.
The below code fails at the last assignment:
static void Main(string[] args)
{
int a = 5;
object b = 5;
System.Diagnostics.Debug.Assert( a is int && b is int );
double x = (double)a;
double y = (double)b;
}
If both a and b are int, what is the cause of this error?
This is an extremely frequently asked question. See https://ericlippert.com/2009/03/03/representation-and-identity/ for an explanation.
Snippet:
I get a fair number of questions about the C# cast operator. The most frequent question I get is:
short sss = 123;
object ooo = sss; // Box the short.
int iii = (int) sss; // Perfectly legal.
int jjj = (int) (short) ooo; // Perfectly legal
int kkk = (int) ooo; // Invalid cast exception?! Why?
Why? Because a boxed T can only be unboxed to T. (*) Once it is unboxed, it’s just a value that can be cast as usual, so the double cast works just fine.
(*) Or Nullable<T>.
Unboxing requires the exact type - you can do this instead:
double y = (double)(int)b;
This is one of the rare cases where System.Convert comes in handy. You can use System.Convet.ToDouble(obj) to knock it out if you don't know before hand that it will be int.
Implicit casting is a compile-time operation. It's not possible for b of type object.
a is an int, but b is a reference to an object that is an int - it is what is called a boxed int. They are two different things, hence the different behaviors.
This question already has answers here:
Closed 13 years ago.
Possible Duplicates:
Casting: (NewType) vs. Object as NewType
Why is the C# “as” operator so popular?
Hey,
I know this may be a silly question but this doubt came to me today.
What is the difference between doing
String text = (String) variable;
and
String text = variable as String;
?
A cast can do three things:
Perform a user-defined conversion
Perform an unboxing conversion
Perform a reference conversion
An as operation is almost always a reference conversion, the only exception being unboxing to a nullable type:
object x = "hello";
int? y = x as int?; // y is null afterwards
Then there's the behaviour with conversions which fail at execution time. So the differences are:
Casts performing reference conversions or unboxing will throw InvalidCastException on failure; as will result in the null value of the target type instead
Casts can perform user-defined conversions; as can't
Casts can unbox to non-nullable value types; as can only be used for unboxing if the target type is a nullable value type
as will return null if variable isn't actually of that type (String in this case). The cast will throw an exception.
Here is the link to Eric Lippert's blog on casting in C#. I'd summarize it, but it's pretty short and he'll explain it much better than me.
http://blogs.msdn.com/ericlippert/archive/2009/10/08/what-s-the-difference-between-as-and-cast-operators.aspx
And here is his post on the cast operator:
http://blogs.msdn.com/ericlippert/archive/2009/03/19/representation-and-identity.aspx
There are a lot of different ways to cast in C#.
This will try to cast the reference to a String reference. If the cast fails, it throws an exception:
string text = (String) variable;
This will try to cast the reference to a String reference. If the cast fails, it will return a null reference to be assigned to the variable:
string text = varible as String;
This will cast a string reference to an object reference, which is a safe casting as String inherits from Object:
object text = (object)"1337";
Casting to a parent class can also be done implicitly:
object text = "1337";
This will box a value inside an object, then unbox it to a plain value again:
int value = 42;
object boxed = (object)value;
int valueAgain = (int)boxed;
The boxing can also be done implicitly:
int value = 42;
object boxed = value;
int valueAgain = (int)boxed;
This will make a widening conversion from byte to int:
byte a = 42;
int b = (int)a;
The same works as an implicit conversion:
byte a = 42;
int b = a;
This will make a narrowing conversion from int to byte, throwing away the overflow:
int a = 512;
byte b = (byte)a; // b now contains 0