3

Recently I am learning value types and I am bit confused. Also both casting and unboxing uses the same syntax - (expected type)(object), right? And what about simple conversion between types, that is casting or just conversion?

int x = (int)2.5; //casting?

object a=x;
int Y=(int)a;  //unboxing I think

Random r=new Random();
object X=r;
Random R=(Random)X;  // casting
Steve
  • 50,173
  • 4
  • 32
  • 41
Lojol
  • 645
  • 3
  • 8
  • 15
  • Hi @Lojol, welcome to Stack Overflow! If you care, you might be able to help us solve a little mystery about the edits in your question. Like: did you change the tags yourself right after asking this? Please see the discussion at our "meta" site: [Pending edit does not reveal any changes, maybe due to edits in grace period?](http://meta.stackexchange.com/questions/75463/pending-edit-does-not-reveal-any-changes-maybe-due-to-edits-in-grace-period) Thanks! – Arjan Jan 19 '11 at 12:25
  • @Steve, same for you! (See my comment above.) Like: did you try to re-order the tags? – Arjan Jan 19 '11 at 12:40

5 Answers5

9

There's a lot of things to consider here, but let's tackle the simplest first:

What is the syntax (type)expression?

Well, in its basic form, it is considered casting. You cast the expression from one type, to another. That's it.

However, what exactly happens, that depends on the type, and a lot of other things.

If casting a value type to something else, you depend on one of the two types involved to declare a casting operator that handles this. In other words, either the value type need to define a casting operator that can cast to that other type, or that other type need to define a casting operator that can cast from the original type.

What that operator does, is up to the author of that operator. It's a method, so it can do anything.

Casting a value type to some other type gives you a different value, a separate value type, or a new reference type, containing the new data after casting.

Example:

int a = (int)byteValue;

Boxing and unboxing comes into play when you're casting a value type to and from a reference type, typically object, or one of the interfaces the value type implements.

Example:

object o = intValue; // boxing
int i = (int)o;      // unboxing

Boxing also comes into play when casting to an interface. Let's assume that "someValueType" is a struct, which also implements IDisposable:

IDisposable disp = (IDisposable)someValueType; // boxed

Casting a reference type, can do something else as well.

First, you can define the same casting operators that were involved in value types, which means casting one reference type to another can return a wholly new object, containing quite different type of information.

Boxing does not come into play when casting a reference type, unless you cast a reference type back to a value type (see above.)

Example:

string s = (string)myObjectThatCanBeConvertedToAString;

Or, you can just reinterpret the reference, so that you still refer to the same object in question, but you are looking at it through a different pair of type glasses.

Example:

IDisposable disp = (IDisposable)someDisposableObject;
Shane Fulmer
  • 7,510
  • 6
  • 35
  • 43
Lasse V. Karlsen
  • 380,855
  • 102
  • 628
  • 825
3

One important restriction on unboxing is that you can only unbox to the exact value-type(or its nullable equivalent) and not to another value-type the original value-type is convertible to.

int myInt = 1;
object x = myInt; // box
int  unbox1 = (int)x;  // successful unbox
int? unbox2 = (int?)x; // successful unbox
long unbox3 = (long)x; // error. Can't unbox int to long
long unbox4 = (long)(int)x; // works. First it unboxes to int, and then converts to long

Another interesting bit is that a nullable value-type gets boxed as its non nullable type, and can be unboxed as both the nullable and the non nullable type. Since a nullable that has the value null boxes to the reference null the information about its type is lost during the boxing.

CodesInChaos
  • 106,488
  • 23
  • 218
  • 262
1

A cast is one form of conversion, basically.

All the comments in your code are correct.

It's important to note the difference between a reference conversion and other conversions, however. The final conversion you've shown is a reference conversion - it maintains representational identity, so the values of X and R are both references to the same object.

Compare this with a double to int conversion (changes form significantly) and unboxing (copies the value from inside the box to the variable).

The difference is important for some topics such as generic variance - that only works with reference types because of the reference conversions available. Basically the CLR checks that it all the types are appropriate, and then runs the appropriate code without ever having to perform any actual conversions on the references themselves.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Thank you. So boxing is just kind of casting? Could I see all this is just casting (type conversion)? – Lojol Jan 19 '11 at 11:52
  • @Lojol: Well, boxing is a form of conversion. You don't need any sort of cast expression to box though - for example your second line of code contains a boxing operation but no cast expression. I tend to think of a cast being present in *source code*, but a *conversion* is what should actually happen due to your code. (And sometimes a conversion can be implicit.) – Jon Skeet Jan 19 '11 at 11:54
  • As there is the same syntax (type)expression it confuses me. I am considering just general terminology, not what is going behind the scenes (which is far behind my knowledge). I made a mistake: I mean, so UNboxing is just kind of casting? – Lojol Jan 19 '11 at 11:57
  • @Lojol: Yes, the same casting syntax is used for both unboxing and explicit reference conversions. I agree it's at least *possibly* regrettable. – Jon Skeet Jan 19 '11 at 12:07
1

Boxing and Unboxing specifically refer to casting value types to reference types and back again. Check out this link for more Boxing and Unboxing (C# Programming Guide).

Ian
  • 33,605
  • 26
  • 118
  • 198
0

Boxing and unboxing is done behind the scenes by compiler. So correct comments would be

int x = (int)2.5; //casting with conversion

object a=x; //casting with boxing
int Y=(int)a;  //casting with unboxing

Random r=new Random();
object X=r;
Random R=(Random)X;  //casting without unboxing

about casting vs conversion check this question: What is the difference between casting and conversion?

Community
  • 1
  • 1
Andrey
  • 59,039
  • 12
  • 119
  • 163