tags:

views:

62

answers:

3

According to MSDN, System.Int32 is immutable, and its members always return new instances. Some common code, like for loop, requires ++ operation quite often. Does increment always create new instances and discard the old ones? As far as I can see, this approach will severely affect the performance. And I wonder how Microsoft implements it.

By the way, is increment thread-safe? In documentation, it says all the members of Int32 are thread-safe, but there is interlocked.increment().

Thanks.

+1  A: 

System.Int32 is not a reference type. Instances are not instantiated by allocating memory in the way that classes are.

Instead, it is a value type. This means that the integer value is copied every time it is assigned to a variable. There is no reference to the integer, just the integer itself.

The ++ operator returns a new integer in a way that would be semantically equivalent to creating a new instance, but it doesn’t actually allocate memory for any object instances.

Timwi
I this context, by saying the word "instance" I mean a value type variable on the stack.
LLS
+2  A: 

Yes and no.

The answer is yes in the sense that this:

i++;

is equivalent to this:

i = i + 1;

which would be equivalent to this (if System.Int32 had a constructor with this signature):

i = new int(i + 1);

BUT...

A constructor for a value type in .NET is in no way the same as a reference type constructor.

The space for a value type is allocated once on the stack. When you write i = i + 1, this is simply writing a new value to the same location in memory. It is not a new allocation on the heap.

This is in fact an implementation detail; but that doesn't change the fact that the answer to what I think you're really asking -- "Does writing i++ require allocating some new memory somewhere?" -- the answer to that question is no.

So, to clarify a few points:

Does increment always create new instances and discard the old ones?

No -- this demonstrates a misunderstanding of the way value types work. It would only make sense to say that incrementing a value "discards the old one" if value types were allocated in some space other than the local stack. It is true that the old value is overwritten, but I hardly think you would find that surprising.

By the way, is increment thread-safe? In documentation, it says all the members of Int32 are thread-safe . . .

Where the documentation says that all members of Int32 are thread-safe, it means with respect to the current value. In fact, any immutable type is going to be thread-safe, because if it cannot be modified, then it cannot be corrupted.

What you must realize is that i++ is not simply a method call on some i value; it is an assignment of i to a new value. This operation -- assigning i to a new incremented value -- is not thread-safe in the sense that two threads might both execute this code concurrently and you can end up with a new value of i that is only 1 greater than the previous value. That is what Interlocked.Increment is for. But the MSDN documentation is not lying to you; the internal state of i is no way compromised by multithreaded access.

Dan Tao
Almost got what I mean. What I really want to know is what will the machine code be? Is it like INC(X), or do some complex operations to create a new integer and overwrite the old value (or even assign a new address in the memory). According to you, I guess it will be like INC(X).
LLS
@LLS: The closest you will get to the machine code is looking at the IL in Reflector. But most optimizations are done by the JIT.
Albin Sunnanbo
A: 

No increment (++) is not thread-safe. The MSDN documentation is correct, but confusing. You need to focus on the second portion.

All members of this type are thread safe. Members that appear to modify instance state actually return a new instance initialized with the new value. As with any other type, reading and writing to a shared variable that contains an instance of this type must be protected by a lock to guarantee thread safety.

What is says is that x+1 is thread safe, since by itself doesn't modify x (think of it as creating a temporary value). But the assignment of x+1 to x is not.

The documentation is also technically correct since ++ is not a member of System.Int32, it is a the C# compiler that translates x++ to x = x + 1.

shf301
Thanks, I thought operator ++ should be considered as one of the members.
LLS
While not thread safe, Int32 assignment is atomic. If a race condition occurs, the last thread to write will win, you will never get a "mix" between the values.
Albin Sunnanbo