Re: Value Types and Reference Types

Tech-Archive recommends: Fix windows errors by optimizing your registry



Jon Slaughter <Jon_Slaughter@xxxxxxxxxxx> wrote:
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.

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."

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).

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

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.

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.

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)

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.

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

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.

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.

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.

--
Jon Skeet - <skeet@xxxxxxxxx>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
World class .NET training in the UK: http://iterativetraining.co.uk
.



Relevant Pages

  • Re: Value Types and Reference Types
    ... the compiler doesn't have a list of them. ... So your saying that an int is not special? ... put it on the stack". ... Int32 x; are pretty much identical except for speed/memory issues. ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: Value Types and Reference Types
    ... So your saying that an int is not special? ... What I mean is that the compiler ... but the main point was that boxing is slow. ... Actually a boxing operation takes 11 machine instruction, 10 instruction to allocate the object space on the heap and 1 instruction to move the value into the object. ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: Value Types and Reference Types
    ... the compiler doesn't have a list of them. ... int is just an alias for System.Int32. ... put it on the stack". ... Int32 x; are pretty much identical except for speed/memory issues. ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: Value Types and Reference Types
    ... Well, the compiler writes IL, and the CLR defines certain IL instructions ... shape just to avoid boxing; chances are that the indirection you'd need to ... I don't mean to sound negative, but the int vs Int32 probably caused ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: Boxing
    ... > Although i am sure that internally no boxing takes place in this case, ... > but surprisingly the compiler does generate the box instruction. ... There's nothing surprising about a box happening here - adding an int ...
    (microsoft.public.dotnet.general)