Is Boxing/unboxing implemented through late or early binding(ie. at runtime or compiletime)?

StackOverflow https://stackoverflow.com/questions/8410308

  •  29-10-2019
  •  | 
  •  

Question

For eg:

int i=10;
object o = i; //late or early??

Similarly,

object o = "11";
int i = (int)o;//late or early??
Was it helpful?

Solution

Is boxing and unboxing implemented through late or early binding? That is, is the binding done at runtime or compile time?

I am a bit confused by the question. "Binding" is typically used to mean the result of some sort of analysis. "Early binding" usually means that some name has been associated with some method slot at compile time; "late binding" associates the name with the slot at runtime. What do you mean by "binding" here in the context of boxing?

I guess you mean to say that late binding comes into play only for method and method calls and not for assignment operations/type conversions. To implement dynamic binding we do reference derived objects with base class variables.

That is not exactly what I meant; I was using method calls as a canonical example that illustrates the difference between early and late binding. I see your point better now; the analysis that determines precisely how a conversion is performed can also be done at runtime or compile time and is therefore in a sense also a form of "late binding" or "early binding".

Let's take as an example this conversion:

int x = Whatever();
short y = (short)x;

That explicit conversion is entirely "bound" at compile time. The compiler knows that the operand is an int, that the target type is short, that the conversion will be performed by truncating the four byte int to a two byte short. The conversion is of course actually performed at runtime.

Now let's make it a bit less clear:

int x = Whatever();
short y = checked((short)x);

The explicit conversion is again bound at compile time. We know how the operation will be performed. But we also know that at runtime the int value will be checked to ensure that it fits into a short.

Does that count as "late binding" in your book? Some of the analysis is performed at compile time but some of the analysis is performed at runtime.

Now let's consider boxing:

int x = Whatever();
object q = x;

This is entirely analyzed at compile time. The compiler knows that q is an object and x is an int, and therefore it will have to issue instructions that box the int at runtime.

What about unboxing?

int x = Whatever();
object q = x;
int y = (int)q;

What analysis is done at compile time? All we know at compile time is that it is an unboxing conversion. The actual type-checking is done at runtime. Is that a form of "late binding" because a type check is performed at runtime, by your definition of late binding?

How about this?

int x = Whatever();
object q = x;
int y = (short)q;

That throws an exception at runtime. At compile time we know that it is an unboxing conversion. At runtime we do not do "late binding" to say "hey, I have a boxed int, let me figure out how to convert that to an unboxed short". Rather, we say "we're trying to unbox an int to short; throw an exception". A boxed T can only be unboxed to a T or a nullable T.

So is unboxing "early bound" or "late bound"? It is early bound in the sense that we know at compile time that it is an unboxing conversion. It is late bound in the sense that we do a type check at runtime. It is not late bound in the sense that we do not at runtime re-do the type analysis that would have been done for an int-to-short conversion at compile time.

What about this?

int x = Whatever();
object q = x;
int y = Convert.ToInt16(q);

or

int x = Whatever();
dynamic q = x;
int y = (int)q;

Now we do perform all that analysis at runtime; in both cases we do the type analysis of q at runtime, determine that q is a boxed int, and "late bind" the conversion.

Is that all clear? It is hard to answer your question because it is a bit vague regarding precisely what you mean by "late binding" a conversion. Which part of the analysis is the "binding" to you?

OTHER TIPS

Boxing is baked into the IL instructions at compile-time if that is what you're looking for.

If you try to unbox into a type other than the original type, an exception would be thrown. Ex#1 it just happens to box implicitly (value type to ref type cast). Ex#2 An invalid cast blows up at runtime.

Not sure how early or late binding comes into the picture.

The compiler will emit boxing instructions that you will be able to see in the IL. Given code

int item = 10;
object obj = item;
item = (int)obj;

You will compile down to something like

IL_0000:  ldc.i4.s    0A 
IL_0002:  stloc.0     
IL_0003:  ldloc.0     
IL_0004:  box         System.Int32
IL_0009:  stloc.1     
IL_000A:  ldloc.1     
IL_000B:  unbox.any   System.Int32
IL_0010:  stloc.0     

In the second version, that's just going to blow up. An object of type string cannot be cast to an integer.

The C# compiles the instructions that are executed at runtime.

Boxing entails a (not inconsiderable) runtime cost; boxing and unboxing can cause runtime errors (as your example "int i = (int)o" illustrates).

"Late binding" vs "early binding" implies something is "dynamic" (for example, runtime binding of some object's virtual method). In this case, boxing is "fixed". So I guess you could say it's "early binding".

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top