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
Related
I have read in CLR via C#:
Unboxing is really just the operation of obtaining a pointer to the
raw value type (data fields) contained within an object.
which means that if more than one value type is contained within an object they can be unboxed using the below syntax:
int a= (int) o; //assigns a to 10
char b= (char) o; // assigns b to 'b'
How to implement such object which supports multiple unboxing?
A boxed value can only be the boxed form of a single type - if you call o.GetType() you'll find out what that is.
In general, you can only unbox to the exact same type, with a few wrinkles:
You can unbox an enum value to its underlying integral type, and vice versa
There's no such thing as a boxed nullable value type - boxing will result in either a boxed form of the non-nullable type, or a null reference. You can unbox to a nullable value type, and the result will either be a null value (if the original reference was a null reference) or a non-null value containing the unboxed non-nullable value, if you see what I mean.
So for example:
object o = 10;
FileMode mode = (FileMode) o; // Valid conversion to enum
int? n = (int?) o; // n has a value of 10
n = null;
o = n; // o's value is a null reference
n = (int?) o; // n's value is the null int? value
Are you talking about casting? In .NET if you have a boxed type it has a specific type and you can only cast it to the actual value type to unbox:
object o=10; // o is a boxed int with value 10
var a=(int)o; // works
//var b=(byte)o; // ERROR, this is not what's contained in it
var b=(byte)(int)o; // works, you get the int out then cast it to byte
var b=Convert.ToByte(o); // also works, using IConvertible
However, the main purpose of generics (initially at least) was to avoid boxing value types at all because of the performance costs involved. You can change most instances of object to generic values and preserve the types, and when you use them you'll have the proper value type right away.
If you have a custom object with for example both an int or a string, you could do this with explicit conversion operators.
Example;
public class CustomObject
{
int Number;
string Text;
public CustomObject(int number, string text) //constructor
{
Number = number;
Text = text;
}
public static explicit operator int(CustomObject o)
{
return o.Number;
}
public static explicit operator string(CustomObject o)
{
return o.Text;
}
}
Fiddle example
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.
This question already has an answer here:
Closed 12 years ago.
Possible Duplicate:
Why does this conversion doesn't work?
Hi,
i discovered a strange behaviour of the framework.
This code throws an exception:
byte a = 1;
object b = a;
Console.WriteLine(b.GetType());
Console.WriteLine((byte)b);
Console.WriteLine((int)(byte)b);
Console.WriteLine(Convert.ToInt32(b));
Console.WriteLine((int)b);
The last line throws a System.InvalidCastException.
I'd like to know what are the mechanism in the framework that make this code illegal.
Is it a problem of boxing/unboxing?!
Yes, boxed value types can only be unboxed to the exact same type.
The variable b is a boxed byte.
When you do (int)(byte)b you're unboxing b back to a byte and then converting that unboxed byte to an int.
When you do (int)b you're attempting to unbox b directly to an int, which is illegal.
Edit...
As Jon mentions in his answer, there are cases where you don't have to unbox to the exact same type. Specifically:
A boxed T can be unboxed to Nullable<T>.
A boxed Nullable<T> can be unboxed to T, assuming that the nullable isn't actually null.
A boxed enum with an underlying type of T can be unboxed to T.
A boxed T can be unboxed to an enum with an underlying type of T.
Eric Lippert has a blog post on this.
Why? Because a boxed T can only be
unboxed to T.
Or Nullable< T >.
When you unbox, it has to be to one of the following:
The exact same type
The nullable form of the exact same type
If it's an enum type value, then you can unbox to the underlying type
If it's an integral type value, you can unbox to an enum which uses that underlying type
Examples:
using System;
class Test
{
enum Foo : short
{
Bar = 1
}
static void Main()
{
short x = 1;
object o = x;
short a = (short) o;
short? b = (short?) o;
Foo c = (Foo) o;
o = Foo.Bar;
short d = (short) o;
}
}
Anything else will give an exception. In particular, you can't unbox to a different type even if there's an implicit conversion from the actual type to your target type, which is what you're trying to do on the last line of your example.
You also can't unbox from an integral value to a nullable form of an enum with the same underlying type (or the reverse situation).
Note that if you box a nullable value type value, the result is either null (if the original value was the null value for the type) or the boxed non-nullable value... there's no such thing as a "boxed nullable value type" if you see what I mean.
Is it a problem of boxing/unboxing?
Yes. bis a boxed byte. So you need to unbox it to a byte first , like in (int)(byte)b
What is type casting, what's the use of it? How does it work?
Casting is usually a matter of telling the compiler that although it only knows that a value is of some general type, you know it's actually of a more specific type. For example:
object x = "hello";
...
// I know that x really refers to a string
string y = (string) x;
There are various conversion operators. The (typename) expression form can do three different things:
An unboxing conversion (e.g. from a boxed integer to int)
A user-defined conversion (e.g. casting XAttribute to string)
A reference conversion within a type hierarchy (e.g. casting object to string)
All of these may fail at execution time, in which case an exception will be thrown.
The as operator, on the other hand, never throws an exception - instead, the result of the conversion is null if it fails:
object x = new object();
string y = x as string; // Now y is null because x isn't a string
It can be used for unboxing to a nullable value type:
object x = 10; // Boxed int
float? y = x as float?; // Now y has a null value because x isn't a boxed float
There are also implicit conversions, e.g. from int to long:
int x = 10;
long y = x; // Implicit conversion
Does that cover everything you were interested in?
Casting means creating a reference to an object that is of a different type to the reference you're currently holding. You can do upcasting or downcasting and each has different benefits.
Upcasting:
string greeting = "Hi Bob";
object o = greeting;
This creates a more general reference (object) from the more specific reference (string). Maybe you've written code that can handle any object, like this:
Console.WriteLine("Type of o is " + o.GetType());
That code doesn't need to be changed no matter what objects you set o to.
Downcasting:
object o = "Hi Bob";
string greeting = (string)o;
Here you want a more specific reference. You might know that the object is a string (you can test this e.g.:
if (o is string)
{ do something }
Now you can treat the reference as a string instead of an object. E.g. a string has a length (but an object doesn't), so you can say:
Console.WriteLine("Length of string is " + greeting.length);
Which you can't do with an object.
See this or this:
Because C# is statically-typed at compile time, after a variable is declared, it cannot be declared again or used to store values of another type unless that type is convertible to the variable's type
...
However, you might sometimes need to copy a value into a variable or method parameter of another type. For example, you might have an integer variable that you need to pass to a method whose parameter is typed as double. Or you might need to assign a class variable to a variable of an interface type. These kinds of operations are called type conversions. In C#, you can perform the following kinds of conversions
Casting from one data type to another.
For a general reading see this.
See also msdn
Also, if you're explicitly casting, you can take advantage of pattern matching. If you have an object:
object aObject = "My string value";
You can safely cast the object as a string in a single line:
if (aObject is string aString)
{
Console.WriteLine("aString = " + aString)
// Output: "aString = My string value"
}
Using this, along with an inverted if statement, you can safely cast types, and fail out early if need be:
public void Conversion(object objA, object objB)
{
// Fail out early if the objects provided are not the correct type, or are null
if (!(objA is string str) || !(objB is int num)) { return; }
// Now, you have `str` and `num` that are safely cast, non-null variables
// all while maintaining the same scope as your Conversion method
Console.WriteLine("str.Length is " + str.Length);
Console.WriteLine("num is " + num);
}