Does unboxing occur when a class's value-type member is referenced?
Asked Answered
O

4

6

I read What is boxing and unboxing and what are the trade offs? but can't understand one thing. Suppose I have a class:

class MyClass
{
    public int Value { get; set; }
}

And I want to get value within my method:

void MyFunc(MyClass cls)
{
    int i = cls.Value;
}

As a class placed in heap, I guess that Value placed in a heap too? And therefore operation

int i = cls.Value;

is unboxing? Or it's not unboxing?

Orthopedics answered 10/1, 2012 at 20:20 Comment(1)
No, that's not unboxing because you are going from an int field to an int local variable. It would be boxing/unboxing if one side was a reference type, so if Value was of type object.Pede
G
17

Stop thinking about stack and heap; that's completely the wrong way to think about it. It is emphatically not the case that "boxed" means "on the heap", and therefore anything "on the heap" must be "boxed".

Stack and heap are irrelevant. Rather, think about references and values. A value of value type is boxed when it must be treated as a reference to an object. If you need to have a reference to a value of a value type, you make a box, put the value in the box, and make a reference to the box. And there, now you have a reference to a value of value type.

Do not confuse that with making a reference to a variable of value type; that is completely different. A variable and a value are two very different things; to make a reference to a variable you use the "ref" keyword.

Guardroom answered 10/1, 2012 at 20:43 Comment(24)
Of what type is a boxed int exactly? Is there a kind of hidden type 'ObjectInt' in the system?Unplumbed
@OlivierJacot-Descombes: A boxed int is of type int. What other type would it possibly be of?Guardroom
So there is a struct int and a class int that coexist?Unplumbed
@OlivierJacot-Descombes: I am not following you in the slightest. Int is a value type; there is no int class. I suspect that you are not reasoning very precisely about what it means for an object to have a type. A boxed int is of type int; an unboxed int is also of type int. I have a cat; she's of the species Felis Catus. I put her in a box and draw an arrow on the floor pointing to the box. She's still of the species Felis Catus. A boxed cat and an unboxed cat are both cats; same with ints. I don't see what you're getting at here.Guardroom
May be I should ask: Of what type is the box of a boxed int?Unplumbed
@OlivierJacot-Descombes: I don't understand what you mean by "what is the type of the box?" Continuing with my analogy to animals: I put a cat in a box, the cat is of type Felis catus. I put a squid in a box; the squid is of type Bathyteuthis abyssicola. Now you are asking me "what are the species of those two boxes?" The boxes do not have a species; they're not even animals in the first place. Values have types; a box is not a value. What do you mean by "what is the type of the box?"Guardroom
The question is invalid, therefore it has no answer (alternatively, the answer is "[mu](en.wikipedia.org/wiki/Mu_(negative)" ( Signifying "unasking" the question or similar) ).Taler
@Eric, is there any case in the current version of .Net when a boxed value type is not stored on the heap? Assuming it is stored somewhere and not optimized away.Resa
@svick: A boxed value is stored on the heap, yes. It could in theory be stored on the temporary store if we knew it was short-lived but in practice we do not perform this optimization. Also, the jitter is not very good about optimizing away boxing. There are scenarios where in order to make the verifier happy we have to box and then unbox immediately; the jitter still performs the boxing unfortunately. However these scenarios are rare.Guardroom
When a squid is placed in a box with a cat, is the cat alive, or dead, or both?Enshroud
@IgbyLargeman: That is the fundamental question of biology: when you put two living things in a box, which one eats the other?Guardroom
@Eric, I'm not sure if this is where Olivier might have been coming from, but in Java (for example), an int is wrapped in an Integer class, double in a Double class, etc. So each value is essentially placed in a different type of box. Whereas it appears the distinction in .NET is that the values are simply placed in an all-purpose box along with (I think) some metadata about the original type, so that a long isn't unboxed to a double.Hyder
While it may be true from a C# perspective that there's no such thing as a "boxed type", note that there is from a CLI perspective (see section 8.2.4 of Partition I of the ECMA CLI spec). "For every value type, the CTS defines a corresponding reference type called the boxed type." However, "A boxed type cannot be directly referred to by name, therefore no field or local variable can be given a boxed type."Ivan
@kvb: And the boxed type cannot be used as a type argument, or a base type, or... anything that a type can be used for. What sense does it make to say "there's a type called the boxed type but you cannot refer to it or use it in any way"? Suppose I told you that there's also a type called the magical unicorn type that you cannot refer to or use in any way -- how is your life improved by knowing that? The "boxed type" is a fiction, just like the magical unicorn type. It does not take part in the type system, so in what possible sense is it a type?Guardroom
As I said, from the perspective of writing C# code, boxed types are not relevant. However, for anyone wishing to emit correct/verifiable IL code, they are relevant because they can occur on the evaluation stack even though they can't be used as storage locations, etc. (in the CLI spec, such types are referred to as "transient types", see section 8.7 of Partition I).Ivan
@kvb: Exactly. The boxed type takes part in the type system of the IL verifier, but not in the type system of the C# language. From the perspective of the C# language, the "boxed type" is entirely fictitious; the reference will be observed to be of the type "reference to object" (or some other reference type).Guardroom
@OlivierJacot-Descombes: Does kvb's comment answer your question? In short: from the perspective of the IL verifier it is possible that a reference is known to be of type "managed pointer to a boxed int", but from the C# language type system's perspective, there is no such thing; a reference to a boxed int is a reference to object. (Or System.ValueType, or whatever.) I am not sure that that answers your question "what is the type of a boxed int?" I was assuming you were asking what the type of the boxed int was: the type of an int is int regardless of whether it is in a box.Guardroom
@kvb: Thanks for pointing this out; I think this might get to what Olivier is fundamentally asking. It is quite a confusing question!Guardroom
Yes, this answers all my questions. Thank you Eric Lippert, Antony Pegram and kvb. Sorry for the confusion.Unplumbed
@OlivierJacot-Descombes: Awesome. The bit in my analogy that I should have been concentrating on to answer your question was not the box but rather the arrow on the floor pointing to the box. Your question was essentially "is there any special fact known about the arrow?" (A "type" is essentially a formalization of a fact known about a thing.) And the answer to that question is yes: the CLR can know that the arrow is pointing to an object that is a box that contains an int. However, the C# language only knows that the arrow points to an object.Guardroom
Yes, the confusion comes from the fact that we have to consider two different levels of abstraction, the C# language and the .NET type system on one side and the low-level technical aspect of the CLR on the other side.Unplumbed
I, for one, would feel a great warmth in my heart to know that there is a magical unicorn type, whether or not I can refer to it or use it in any way. It would make the world a very different, better place.Enshroud
Yes, Igby, there is a magical unicorn type. It exists as certainly as love and generosity and devotion exist, and you know that they abound and give to your life its highest beauty and joy. Alas! how dreary would be the world if there were no magical unicorn type!Guardroom
Thank you Eric. My heart overflows with double rainbows.Enshroud
N
10

Boxing or unboxing doesn't have anything to do with storing values on heap or stack. You should read the article "Boxing and Unboxing" from the C# Programming Guide. In your example none of these two occurs because you're assigning int to int.

Noahnoak answered 10/1, 2012 at 20:25 Comment(0)
S
7

It's neither unboxing nor boxing. Considering you assign to int without cast and, I hope, this code compiles, that means that cls.Value is a Integer(int) type. So assign int to int. What happens here is a value copy.

Slightly answered 10/1, 2012 at 20:24 Comment(0)
U
0
int i = 5;
object o = i;   // boxing of int i
int i = (int)o; // unboxing of object o

Note that we do not assign i to a field or property of an object, but to the object itself. It is comparable to the nature of light. Light can be perceived of being made of particles (photons) or being a wave. An int can be an int object (a reference type) or an int value type. You can however not define an int to be a reference type directly; you must convert it to an object, e.g. by assigning it to a variable, parameter or property of type object or casting it to object to make it a reference type.

Unplumbed answered 10/1, 2012 at 20:31 Comment(5)
So when I say "((object)123).ToString()", is that not boxing? Because where is the variable, parameter or property of type object to which the value is being assigned? This explanation does not hold any water.Guardroom
Ok, I forgot casting! (I changed the Text).Unplumbed
OK, what if you call 123.GetType()? GetType is a non-virtual method defined on System.Object, and therefore requires a reference to object as its "this" parameter. Is this not a boxing because there is no assignment or cast? You are approaching this from the wrong direction. Boxing is a form of conversion. That is what is fundamental here.Guardroom
@EricLippert conversion from what to what? According to kvb's comment to your answer, from the CTS point of view, the conversion is from a value type to its "corresponding reference type called the boxed type". From this point of view, the answer to Olivier's question "of what type is boxed int" is "boxed int". Not a very satisfying answer, I suppose.Burn
@phoog: A conversion from, say, int to object, is a boxing conversion. It's a boxing conversion because it allocates a box that can hold an int and copies the int into the box.Guardroom

© 2022 - 2024 — McMap. All rights reserved.