Value Types and Reference Types

D

Dom

Let me explain my mental image, and then tell me where I've gone
wrong.

There is a stack and a heap. A reference type sits on the heap, and
its address sits on the stack. When you pass it to a method, you pass
the contents of the stack, which is the same as passing the address of
the object.

A value type just sits on the stack. When you pass it to a method,
you pass the contents of the stack, just as before. Only now the
method knows not to "dereference" it.

Now, here's the problem. I had a method that received an integer, and
I wanted to modify it so it could also receive a DateTime. I could
have overloaded the method, but because I am stuck in VB-think, i just
changed the argument from integer to object, assuming it worked like
VB's "Any". And it worked. But according to my mental image, the
method should have taken the value sent and tried to look it up on the
heap, and then fail. Or the compiler should have complained about a
mismatch.

What happened?
 
J

Jon Skeet [C# MVP]

Dom said:
Let me explain my mental image, and then tell me where I've gone
wrong.

There is a stack and a heap. A reference type sits on the heap, and
its address sits on the stack. When you pass it to a method, you pass
the contents of the stack, which is the same as passing the address of
the object.

Well, the address might sit on the stack - or it might sit on the heap,
depending on where it's being referenced from.

See http://pobox.com/~skeet/csharp/memory.html
A value type just sits on the stack. When you pass it to a method,
you pass the contents of the stack, just as before. Only now the
method knows not to "dereference" it.
Ditto.

Now, here's the problem. I had a method that received an integer, and
I wanted to modify it so it could also receive a DateTime. I could
have overloaded the method, but because I am stuck in VB-think, i just
changed the argument from integer to object, assuming it worked like
VB's "Any". And it worked. But according to my mental image, the
method should have taken the value sent and tried to look it up on the
heap, and then fail. Or the compiler should have complained about a
mismatch.

What happened?

Boxing, basically. It's probably easiest to look up "boxing" in C# book
rather than me trying to expain it all right now (when I'm meant to be
working ;)
 
J

Jon Skeet [C# MVP]

Chris Dunaway said:
Yeah, don't Distract Jon from getting that book out!! ;)

LOL - if only I meant that kind of work! Fortunately all the work there
is finished now - although I want to make a few more changes to the
website, do the spec map etc...
 
J

Jon Slaughter

Dom said:
Let me explain my mental image, and then tell me where I've gone
wrong.

There is a stack and a heap. A reference type sits on the heap, and
its address sits on the stack. When you pass it to a method, you pass
the contents of the stack, which is the same as passing the address of
the object.

A value type just sits on the stack. When you pass it to a method,
you pass the contents of the stack, just as before. Only now the
method knows not to "dereference" it.

Now, here's the problem. I had a method that received an integer, and
I wanted to modify it so it could also receive a DateTime. I could
have overloaded the method, but because I am stuck in VB-think, i just
changed the argument from integer to object, assuming it worked like
VB's "Any". And it worked. But according to my mental image, the
method should have taken the value sent and tried to look it up on the
heap, and then fail. Or the compiler should have complained about a
mismatch.

All types derive from System.Object. Value types are special types that can
"fit" on the stack. The compiler basically has a list of types that are
special and will stick them on the stack instead of the heap when used.
(struct is a general type that gets this priviledge but is made up of the
more simple types)

BUT, if those value types are told to be put on the heap then they will.
i.e., If you tell the compile you want to treat it as a ref type then it
will "convert" it to a reference type and use the heap instead.

e.g.,

int x;

gives a value type x.

System.Int32 x;

will give a referenec type x;

Basically the compiler says "Oh, x is a value type so we can optimize it and
put it on the stack". If you do int x and then object y = (object)x. Then
the compiler will convert x into an object(after all, its base type is an
object since they all derive from it). This is slow cause now the compiler
has to create the object on the heap and its called boxing.

I think if you think of it as an optimization of special types then its not
a difficult concept. Basically using the special keywords you tell the
compiler they are value types... which just means that they are to be
optimized and put on the stack rather than the heap. And remember that if
you convert from optimized to non-optimzed or vice versa that there is a
penalty.

Other than that they pretty much are exactly the same. Again, int x and
Int32 x; are pretty much identical except for speed/memory issues. The heap
and stack are just memory. An object has more overhead of course and thats
why value types are faster. No reason to have overhead for something like

int x = 3;
int y = 9;
int z = x * y;

The compiler will simply do that in the most optimized way which is using
the ALU of the cpu(done in 1-2 instructions in assembly).

if you do

Int32 x = 3;
Int32 y = 9;
Int32 z = x * y;

then the compiler will treat them as full blown objects and have to find the
operator *, call the constructors, allocate memory, etc... Theres no need
for that. (although its a simple example so...)


Hope that helps,
Jon
 
J

Jon Skeet [C# MVP]

Jon Slaughter said:
All types derive from System.Object. Value types are special types that can
"fit" on the stack. The compiler basically has a list of types that are
special

No, the compiler doesn't have a list of them. The type metadata
determines whether or not it's a value type.
and will stick them on the stack instead of the heap when used.

Well, that depends:
http://pobox.com/~skeet/csharp/memory.html
(struct is a general type that gets this priviledge but is made up of the
more simple types)

Struct isn't a type in itself, it's just the way you declare a value
type in C#.
BUT, if those value types are told to be put on the heap then they will.
i.e., If you tell the compile you want to treat it as a ref type then it
will "convert" it to a reference type and use the heap instead.

e.g.,

int x;

gives a value type x.

System.Int32 x;

will give a referenec type x;

No it won't. int is just an alias for System.Int32. The two lines of
code above are exactly equivalent.
Basically the compiler says "Oh, x is a value type so we can optimize it and
put it on the stack". If you do int x and then object y = (object)x. Then
the compiler will convert x into an object(after all, its base type is an
object since they all derive from it). This is slow cause now the compiler
has to create the object on the heap and its called boxing.

Well, I wouldn't say it's actually slow. It will cause a performance
hit if you do it millions and millions of times, but it's no slower
than creating other objects.
I think if you think of it as an optimization of special types then its not
a difficult concept. Basically using the special keywords you tell the
compiler they are value types... which just means that they are to be
optimized and put on the stack rather than the heap. And remember that if
you convert from optimized to non-optimzed or vice versa that there is a
penalty.

Other than that they pretty much are exactly the same. Again, int x and
Int32 x; are pretty much identical except for speed/memory issues. The heap
and stack are just memory. An object has more overhead of course and thats
why value types are faster. No reason to have overhead for something like

There's more to it than that. See
http://pobox.com/~skeet/csharp/references.html
int x = 3;
int y = 9;
int z = x * y;

The compiler will simply do that in the most optimized way which is using
the ALU of the cpu(done in 1-2 instructions in assembly).

if you do

Int32 x = 3;
Int32 y = 9;
Int32 z = x * y;

then the compiler will treat them as full blown objects and have to find the
operator *, call the constructors, allocate memory, etc... Theres no need
for that. (although its a simple example so...)

It's also an incorrect example, for the reason given earlier.
 
J

Jon Slaughter

Jon Skeet said:
No, the compiler doesn't have a list of them. The type metadata
determines whether or not it's a value type.

So your saying that an int is not special? What I mean is that the compiler
has internal types that essentially are representable by the cpu's logic.
The cpu doesn't know how to add a two classes together even if one defines
an operator... but it knows how to add two words. I'm not sure of the
terminology though but there definitely are special types that can be dealt
with by the cpu itself. These are the most basic types that everything else
is built up from.

Well, that depends:
http://pobox.com/~skeet/csharp/memory.html


Struct isn't a type in itself, it's just the way you declare a value
type in C#.

well, maybe not but a meta type at least. Its a "container" of value
types(although this isn't necessary I suppose).
No it won't. int is just an alias for System.Int32. The two lines of
code above are exactly equivalent.

Ok, well, there are objects of int type. I thought Int32 was the object
representative of int. I thought there was some object type for int in
..NET? If not then there is at least an internal type that is used? Else
there would be no way to box?

unless boxing doesn't create an object on the heap but just copiest the
value type? In that cause its still like an paired down object.
Well, I wouldn't say it's actually slow. It will cause a performance
hit if you do it millions and millions of times, but it's no slower
than creating other objects.

Yes, but the main point was that boxing is slow. Creating objects from
classes is necessary but boxing isn't(maybe in certain cases of course but
there is a difference)

I'm sure there is ;) I was trying to explain to the OP in a conceptual way
what the difference in. I think I did that but not so good with a few
errors(although I think the overall concept is correct but could have been
written better with more accuracy).
It's also an incorrect example, for the reason given earlier.

Let Int32 be an object then and it shows the point. Of course the problem
then includes casting or writing an operator or something else.

Surely .NET has the object "version" of the simple value types(primitive)
that one can get too? Or is it just handled internally and optimized when
boxing?

In fact, if .NET used System.Int32 as the object then it would be easier for
me to explain how boxing works and why its slower ;)

(the examples above would nee dto be modified though such as

Int32 x = new Int32(3);
etc..

)
 
J

Jon Slaughter

I suppose actually what I should have done is

(all public)

struct word
{
int x;
word(int x)
{ this.x = x; }
}


class wordobj
{
int x;
wordobj(int x)
{ this.x = x; }
}


and assume there is a type converter.

Essentially these two things represent the same thing... but the compiler
treats them differently.

word y = 3; (assume it works... should be new word(3))
wordobj z = 3

wordobj k = (wordobj)y; (boxing)

Now both are essentially the same but one is created on the stack and the
other on the heap.

Whats the real difference? just optimization. Its easier to put things on
the stack than the heap(ok, maybe not really that much harder) and its
usually more efficient because of the cpu's cache and stuff.

In a sense what I'm trying to get at is that the struct is like a
lightweight version of a class. A value type is a primitive type that the
cpu can deal with directly and objects are compound versions of these types.
The compiler can easily put objects on the stack too with no issue but
stacks are small and objects tend to be large.

In fact I can't see any difference between word and wordobj except that the
compiler treats word as a special type and knows that it should try to put
it on the stack for optimization reasons(else theres no reason... if there
was no stack then there is no reason because one has to allocate memory).

So the issue is only because of one using a stack and heap and nothing else.
value types get on stack, reference types get on heap. Converting a value
type to a reference type create an object and hence it gets put on heap. Its
slower and less efficient.

Optimization is the only reason why value types exist and technically they
are not even needed. (one could do everyone using reference types if they
wanted(well, almost... the cpu needs to be used to do the most basic logic))
 
M

Marc Gravell

So your saying that an int is not special? What I mean is that the
compiler has internal types that essentially are representable by
the cpu's logic.

Well, the compiler writes IL, and the CLR defines certain IL instructions
for some types - for instance the "add" instruction. This is a *little*
different to user-code, in that normally you would have an operator (static
op_Addition method) against the type [which isn't the case for Int32].
It is the JIT's job to map the IL instructions to CPU instructions, and
there is no fundamental guarantee that this is a direct CPU operation. But
in reality it tends to be.
well, maybe not but a meta type at least. Its a "container" of value
types(although this isn't necessary I suppose).

"struct" has no real meaning except for as a C# type declaration, and as a
generic constraint. A value-type instance may contain either value-types or
references to reference-types.
Ok, well, there are objects of int type. I thought Int32 was the object
representative of int.

You can box an Int32==int, but you can box any type.
unless boxing doesn't create an object on the heap but just copiest the
value type? In that cause its still like an paired down object.

The box /is/ on the heap, but yes: it just copies the value.
Yes, but the main point was that boxing is slow. Creating objects from
classes is necessary but boxing isn't(maybe in certain cases of course but
there is a difference)

Compared to what? It isn't *very* slow. I wouldn't bend a design out of
shape just to avoid boxing; chances are that the indirection you'd need to
accomodate this would nillify any saving. Generics are a good way of
avoiding boxing, but have their own limitations.

Sorry; I don't mean to sound negative, but the int vs Int32 probably caused
a lot of unnecessary confusion here. So to reiterate - they are exactly the
same thing.

Marc
 
M

Marc Gravell

Seriously - don't fret over stack vs heap - that isn't the point...

Whats the real difference? just optimization.

No; the value-vs-reference semantic is the difference
In a sense what I'm trying to get at is that the struct is like a
lightweight version of a class. A value type is a primitive type that the
cpu can deal with directly and objects are compound versions of these
types.

No; only things like Int32==int, Single==float and Double==double are likely
to have any real direct CPU advantage (courtesy of the JIT); other than that
it is just code. Decimal is a value type, and has no CPU advantage; ditto
"word"
The compiler can easily put objects on the stack too with no issue but
stacks are small and objects tend to be large.

Most individual objects actually tend to relatively small; only arrays etc
are noticeably big, and beyond a certain size they will go on the special
"large object heap".
In fact I can't see any difference between word and wordobj except that
[snip]

word foo = new word(1);
word bar = foo;

how many words are there? now do the same exercise with wordobj.
Now both are essentially the same but one is created
on the stack and the other on the heap.

Depends; if that code is field initializers in a class then it all goes on
the heap.
value types get on stack, reference types get on heap.

A common over-simplification. In short: a myth.

Marc
 
J

Jon Skeet [C# MVP]

Jon Slaughter said:
So your saying that an int is not special? What I mean is that the compiler
has internal types that essentially are representable by the cpu's logic.

int is only special to the C# compiler in two ways:

1) It knows that it's an alias for System.Int23.
2) It knows that there are specific IL instructions for handling
System.Int32

The C# compiler (at least Microsoft's one targeting .NET) doesn't
usually know what CPU your code will eventually run on.

However, you picked an unfortunate example - one where the compiler
does genuinely have extra information. Now let's looks at
System.Drawing.Point. The compiler has no information about that struct
built into it - it has to find out that it's a value type the same way
it finds out about its methods etc, by looking at the metadata.
The cpu doesn't know how to add a two classes together even if one defines
an operator... but it knows how to add two words. I'm not sure of the
terminology though but there definitely are special types that can be dealt
with by the cpu itself. These are the most basic types that everything else
is built up from.

Sure - but that's irrelevant to your original claim that "The compiler
basically has a list of types that are special and will stick them on
the stack instead of the heap when used."
well, maybe not but a meta type at least. Its a "container" of value
types(although this isn't necessary I suppose).

You may be meaning System.ValueType, but really the word "struct" does
not represent a "container" of value types in any way.
Ok, well, there are objects of int type. I thought Int32 was the object
representative of int. I thought there was some object type for int in
.NET? If not then there is at least an internal type that is used? Else
there would be no way to box?

Every value type automatically has a boxed type with the same name. C#
makes it hard to spot the difference really, but in C++/CLI I believe
you can distinguish between the two types. (Ben, confirm or deny?)
unless boxing doesn't create an object on the heap but just copiest the
value type? In that cause its still like an paired down object.

Boxing definitely creates an object on the heap.
Yes, but the main point was that boxing is slow. Creating objects from
classes is necessary but boxing isn't(maybe in certain cases of course but
there is a difference)

Boxing is slower than not boxing, in that doing something is almost
always slower than not doing it. But that's not the same as saying it's
slow. Is adding two numbers slow? How about calling a method? Just how
slow do you think boxing is?

Here's a micro-benchmark - unreliable as all micro-benchmarks are, but
it genuinely does do boxing, a billion times:

using System;
using System.Diagnostics;

public class Test
{
const int Iterations = 1000*1000*1000;

static void Main()
{
// Just to make sure there's no initial hit
int dummy = 10;
object o2 = dummy;

Stopwatch sw = Stopwatch.StartNew();
int j = 5;
for (int i=0; i < Iterations; i++)
{
object o = j;
}
sw.Stop();
Console.WriteLine (sw.ElapsedMilliseconds);
}
}

On my laptop (running on "balanced" power mode, even) it executes in
about 8.6 seconds. In other words, it's boxing over 100 *million* times
per second. Is that really your idea of a slow operation?

Yes, boxing should be avoided where it can be - for various reasons.
It's hugely unlikely to become a performance bottleneck in most
programs though, and using the word "slow" is likely to give people the
wrong impression.
I'm sure there is ;) I was trying to explain to the OP in a conceptual way
what the difference in. I think I did that but not so good with a few
errors(although I think the overall concept is correct but could have been
written better with more accuracy).

Sorry, but I think your explanation was more error than fact. It didn't
deal with the *important* differences between value types and reference
types, and made a bunch of mistakes along the way.
Let Int32 be an object then and it shows the point. Of course the problem
then includes casting or writing an operator or something else.

Surely .NET has the object "version" of the simple value types(primitive)
that one can get too? Or is it just handled internally and optimized when
boxing?

It's mostly handled invisibly as far as C# is concerned.
In fact, if .NET used System.Int32 as the object then it would be easier for
me to explain how boxing works and why its slower ;)

Yes - but fortunately the platform designers had more important
concerns than making inaccurate explanations coincidentally correct.
 
J

Jon Skeet [C# MVP]

Whats the real difference? just optimization. Its easier to put things on
the stack than the heap(ok, maybe not really that much harder) and its
usually more efficient because of the cpu's cache and stuff.

In a sense what I'm trying to get at is that the struct is like a
lightweight version of a class.

No, you've completely missed the point of the distinction between value
types and reference types.

*Please* read
http://pobox.com/~skeet/csharp/references.html
and
http://pobox.com/~skeet/csharp/parameters.html
before making any more claims like this.

In particular, consider the following program:

using System;
using System.Text;

public class Test
{
static void Main()
{
StringBuilder builder = new StringBuilder();
StringBuilder otherBuilder = builder;
builder.Append("Hi");

Console.WriteLine(otherBuilder.ToString());
}
}

If your explanation was correct, it would make no difference to the
output (optimisation shouldn't affect output, right?) whether
StringBuilder is a value type or a reference type. The reality couldn't
be more different.
 
J

Jon Slaughter

Marc Gravell said:
So your saying that an int is not special? What I mean is that the
compiler has internal types that essentially are representable by
the cpu's logic.

Well, the compiler writes IL, and the CLR defines certain IL instructions
for some types - for instance the "add" instruction. This is a *little*
different to user-code, in that normally you would have an operator
(static op_Addition method) against the type [which isn't the case for
Int32].
It is the JIT's job to map the IL instructions to CPU instructions, and
there is no fundamental guarantee that this is a direct CPU operation. But
in reality it tends to be.
well, maybe not but a meta type at least. Its a "container" of value
types(although this isn't necessary I suppose).

"struct" has no real meaning except for as a C# type declaration, and as a
generic constraint. A value-type instance may contain either value-types
or references to reference-types.
Ok, well, there are objects of int type. I thought Int32 was the object
representative of int.

You can box an Int32==int, but you can box any type.
unless boxing doesn't create an object on the heap but just copiest the
value type? In that cause its still like an paired down object.

The box /is/ on the heap, but yes: it just copies the value.
Yes, but the main point was that boxing is slow. Creating objects from
classes is necessary but boxing isn't(maybe in certain cases of course
but there is a difference)

Compared to what? It isn't *very* slow. I wouldn't bend a design out of
shape just to avoid boxing; chances are that the indirection you'd need to
accomodate this would nillify any saving. Generics are a good way of
avoiding boxing, but have their own limitations.

I've read they were slow and from my own experience I've had some issues.
Slow is relative. I'm not saying avoid it but that you need to be aware. If
you are boxing a lot of stuff in a loop then it can be significantly slower.
Its just something to be aware of.
Sorry; I don't mean to sound negative, but the int vs Int32 probably
caused a lot of unnecessary confusion here. So to reiterate - they are
exactly the same thing.

Yes, I was wrong there. I thought the Int32 was the reference type for int.
I'm not sure why I thought that even when I used it before(or at least saw
it in other code). I suppose I thought because they explicity had two
different names then they should be different. I thought I read somewhere
that there were reference based equivalents for all primitive types but I
guess not? i.e., everything derives from system.object? (if so then there
are but I guess the primitive types do not have explicit corresponding
reference types?)
 
J

Jon Slaughter

(BTW, I don't mean everything I say is exactly correct but it seems to make
sense ;) I'm sure C# and .NET can easily do what they want. e.g., its not
necessary at all for a struct to be allocated on the stack. Just that CLR
seems to use structs in a special way and really it comes down to the "light
weight" object kinda idea.
 
J

Jon Skeet [C# MVP]

This is one of few correct things in your post. Yes, in some ways a
struct can be thought of as a lightweight version of a class. It's not
really exactly that, but you're not too far from the mark here.

Ironically, that's one of the things I'd flag up as "absolutely wrong"
too. The "lightness" of a struct or a class depends on the exact
situation. Consider a struct containing a hundred System.Guid member
variables, and then consider a class of the same nature. Now imagine a
method taking that type as a parameter, and think about how much needs
to be copied when the method is called in each case - which feels
lighter? ;)

By definition, a reference type is allocated on the heap.

Just to introduce a slightly esoteric point here - this is true for
..NET, but C# itself doesn't mention the stack vs heap at all. I only
mention this because when C# in Depth was going through tech review,
the reviewer suggested that really managed code developers shouldn't
care about stacks or heaps, and that it's an implementation detail.

The C# compiler (even for .NET) *could* create classes for each set of
local variables, and barely use the stack at all. Indeed, with captured
variables and iterator blocks we're already past the stage of being
able to say that local variables are always on the stack.

When targeting a different platform, the C# compiler could write code
which built objects on the stack, so long as it was absolutely certain
that the semantics would stay the same. (This already exists with
stackalloc and arrays, but not general reference types.)

I'm not sure to what extent I agree with the idea that we shouldn't
really care - there *are* cases where it makes a difference - but it's
an interesting thing to consider.
It's not true that optimization is "the only reason why value types
exists". However, you are correct that technically they are not even
needed. But Java demonstrates quite well that not having value types is
not a prerequisite for performance either. Having value types helps a
little, but Java programs get by just fine without them and Java's
performance does not suffer much at all because of the lack of them.

Um, Java *does* have value types - int, byte etc. It's just that you
can't create your own *new* value types.
 
J

Jon Skeet [C# MVP]

Peter Duniho said:
Value type inheritance from System.Object is a special case, so that all
types in .NET share the common behavior defined in that type. There's no
need for a special "reference type" version of value types to support that.

A reference type version *is* required to support boxing, however.
Frankly the CLI and C# specs are pretty confusing in this respect - I'm
glad that I don't have to pick over the minutiae of them very often :)
 
J

Jon Skeet [C# MVP]

Peter Duniho said:
But is that not automatically generated and/or a hidden part of the CLI
implementation?

Well, boxing is defined in the C# language spec (section 4.3.1). It's
pretty vague about what goes on under the C# layer.

However, the CLI *spec* (rather than just implementation) is quite
precise about it. (Confusing, but precise.)
That is, that's a distinction that is not apparent or relevant to the C#
programmer, as far as I know.

Well, I think it makes sense that there has to be a reference type
involved. Consider:

object x = 123;

The value of x is a non-null reference, it refers to an object with a
type. It must be a reference type because there's a reference to it,
but it acts in many ways as if it were the same type as System.Int32
(in terms of behaviour with "is" etc).

There are other ways in which it acts like a reference type, by the
way, which are made apparent if you use a mutable value type which
implements an interface allowing the mutation - that lets you change
the "value in the box" and you can observe reference type semantics:

using System;

interface IDodgy
{
void SetValue(int value);
}

struct Dodgy : IDodgy
{
int x;

public void SetValue(int value)
{
x = value;
}

public override string ToString()
{
return x.ToString();
}
}

public class Test
{
static void Main()
{
Dodgy a = new Dodgy();

IDodgy box1 = a;
IDodgy box2 = box1;

box1.SetValue(10);
// Prints 10, i.e. reference type semantics
Console.WriteLine(box2);
}
}

The easiest way to think about it, IMO, is actually to think about the
model that the CLI spec uses.

However, I agree that it's a pretty arcane distinction to make :)
 
W

Willy Denoyette [MVP]

Jon Skeet said:
int is only special to the C# compiler in two ways:

1) It knows that it's an alias for System.Int23.
2) It knows that there are specific IL instructions for handling
System.Int32

The C# compiler (at least Microsoft's one targeting .NET) doesn't
usually know what CPU your code will eventually run on.

However, you picked an unfortunate example - one where the compiler
does genuinely have extra information. Now let's looks at
System.Drawing.Point. The compiler has no information about that struct
built into it - it has to find out that it's a value type the same way
it finds out about its methods etc, by looking at the metadata.


Sure - but that's irrelevant to your original claim that "The compiler
basically has a list of types that are special and will stick them on
the stack instead of the heap when used."


You may be meaning System.ValueType, but really the word "struct" does
not represent a "container" of value types in any way.


Every value type automatically has a boxed type with the same name. C#
makes it hard to spot the difference really, but in C++/CLI I believe
you can distinguish between the two types. (Ben, confirm or deny?)


Boxing definitely creates an object on the heap.


Boxing is slower than not boxing, in that doing something is almost
always slower than not doing it. But that's not the same as saying it's
slow. Is adding two numbers slow? How about calling a method? Just how
slow do you think boxing is?

Here's a micro-benchmark - unreliable as all micro-benchmarks are, but
it genuinely does do boxing, a billion times:

using System;
using System.Diagnostics;

public class Test
{
const int Iterations = 1000*1000*1000;

static void Main()
{
// Just to make sure there's no initial hit
int dummy = 10;
object o2 = dummy;

Stopwatch sw = Stopwatch.StartNew();
int j = 5;
for (int i=0; i < Iterations; i++)
{
object o = j;
}
sw.Stop();
Console.WriteLine (sw.ElapsedMilliseconds);
}
}

On my laptop (running on "balanced" power mode, even) it executes in
about 8.6 seconds. In other words, it's boxing over 100 *million* times
per second. Is that really your idea of a slow operation?

You can make the above even faster when building with /o+ ;-)
Actually a boxing operation takes 11 machine instruction (assuming is no GC
is introduced), 10 instruction to allocate the object space on the heap and
1 instruction to move the value into the object. So, boxing performance is
merely a matter of memory latency.



Willy.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top