18

Just ran into a bit of code that wasn't doing what I thought it should. Do other people think this should return 1? Is there a good explanation as to why it doesn't??

int count = 0;

count++.ToString(); // Returns 1 no?

I always thought count++ was the same as count = count + 1...

John Saunders
  • 160,644
  • 26
  • 247
  • 397
swingdoctor
  • 1,551
  • 2
  • 11
  • 18

6 Answers6

46

x++ is a post increment operator. It means that the value of x is incremented, but the old (non-incremented) value of x is returned (0 in your case, to which ToString is applied).

To get the behavior you want, use the pre increment operator ++x.

Heinzi
  • 167,459
  • 57
  • 363
  • 519
  • sweet...all these years and I thought the positioning of the ++ was just programmer preference. cheers – swingdoctor Feb 17 '11 at 15:28
  • 1
    @swingdoctor Assumptions - the mother of all... ;) – Fredrik Norlin Feb 17 '11 at 16:00
  • 1
    `++x` can also be faster than `x++` in some languages (because the original value has to be copied and stored separately to be returned with the post-increment). In general I think it's a good idea to always use the pre-increment operator as the post-increment operator rarely has the intended result when the difference matters. – Andrew Marshall Feb 17 '11 at 16:15
  • 11
    @Andrew: That difference has got to be measured in nanoseconds. If your program is so fast that a difference of a couple nanoseconds is relevant then you probably don't want to be using a garbage-collected language on a preemptively multitasking operating system in the first place. – Eric Lippert Feb 17 '11 at 16:26
  • 2
    @Eric The speedup is certainly extremely small, I just see it as a little plus to using the technique that results in (what I think at least) is the expected behavior. There's no reason I can see _not_ to use the pre-increment operator instead outside of specific cases. And I was thinking mostly of C/C++ :) – Andrew Marshall Feb 17 '11 at 16:31
  • @Andrew: If you turn optimization on and examine gen'd code in a case where the semantics of x++ and ++x would otherwise be identical, there is frequently no difference whatsoever. – Greg D Feb 17 '11 at 17:50
  • @Eric: I also use ++i all the time in for loops because I also read that it was faster than i++ when I first started using C#. Is this bad? The only downside I see is maybe this would confuse some C++ programmers, but I don't really care much about them, and from what I know this originates from C++, isn't it? On the other hand, it isn't harder to use/type ++i than i++. What do you think? – Joan Venge Feb 17 '11 at 17:53
  • @Greg even without optimization the assembly is the same with gcc 4.2 (well, same instructions, different order). Though certain situations with regard to that status of registers and the stack could cause one to be faster than the other. It could also vary by compiler and language, I've heard people say that it's quicker in Java, but never seen any proof. Regardless, as Eric said the speedup is almost always negligible, likely no more than one, maybe two instructions. Writing straight assembly you could save one instruction with pre-increment by using registers only. – Andrew Marshall Feb 17 '11 at 18:45
  • 7
    @Joan: I think that if you're doing something for a performance reason then there should be a measurement that demonstrates that the code change makes a significant difference that is meaningful to a customer. If there is no such measurement then make implementation choices based on criteria other than performance. – Eric Lippert Feb 17 '11 at 19:13
  • Thanks Eric, I agree with you. – Joan Venge Feb 17 '11 at 19:21
  • 1
    A non-performance criteria is semantics. Post-increment says to the reader, "I want to increment AND do something with the previous value." Pre-increment simply says, "I want to increment." I often see post-increment, when the usage in the code calls for pre-increment. It's a little bit of semantic mismatch that causes mental friction when reading the code. – Ben Feb 23 '11 at 19:33
17

At least four of the answers posted so far are wrong. It is an extremely common error to believe that the ++ operator has the same ill-defined semantics as it does in C. It does not. The semantics of the ++ operator are well-defined, and are quite different from how they have been described by the incorrect answers here. See my answer to the last time this question was asked for details:

What is the difference between i++ and ++i?

Community
  • 1
  • 1
Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
  • +1, very insightful, as usual. I've modified my answer to avoid the implication that this has something to do with "happens before". – Heinzi Feb 17 '11 at 16:54
8

x++ is post increment; the current value (0) is used as the result, then the ++ happens.

A bit like:

var tmp = count;
count++;
Consle.WriteLine(tmp);

The pre-increment (++x) would behave as you expected.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
2
(++i).ToString();

does exactly what you expect.

Bala R
  • 107,317
  • 23
  • 199
  • 210
  • It's one oddity of the compiler. c++.ToString() compiles, but ++c.ToString() doesn't...! However, implicit casting the ++c will work hence (++c).ToString(). Weird... – code4life Feb 17 '11 at 15:23
  • @code4life: Not an oddity, just a consequence of operator binding precedence... `++c.ToString()` is an attempt to preincrement the string returned by `ToString()` – Chris Dickson Feb 17 '11 at 15:27
1

Your original code will always show 0.

Try this:

(++c).ToString();

This will return 1.

From the MSDN site:

The first form is a prefix increment operation. The result of the operation is the value of the operand after it has been incremented.

The second form is a postfix increment operation. The result of the operation is the value of the operand before it has been incremented.

code4life
  • 15,655
  • 7
  • 50
  • 82
  • The last sentence is absolutely wrong. The increment always happens *before* the call to ToString() regardless of the position of the ++. If you don't believe me, try it: static class X { public static void M(this int x) { Console.WriteLine(C.c); } } class C { int public static int c = 0; static void Main() { (C.c++).M(); } } As you can see, the increment of C.c happens **before the call**, not **after the execution of the line**. C# guarantees that side effects happen in left-to-right order. – Eric Lippert Feb 17 '11 at 16:06
  • See http://stackoverflow.com/questions/3346450/c-what-is-the-difference-between-i-and-i/3346729#3346729 for more details. – Eric Lippert Feb 17 '11 at 16:15
-2

No, ++count return "1". count++.ToString() execute the ToString() method and then increments count, so it returns "0".

Sebastien
  • 80
  • 1
  • 7
  • The second sentence is wrong. See http://stackoverflow.com/questions/3346450/c-what-is-the-difference-between-i-and-i/3346729#3346729 for the reason why. – Eric Lippert Feb 17 '11 at 16:14
  • Reading your comment, I Had a doubt, and then I wrote this. It confirms i wasn't wrong : public static void Main() { int cpt = 0; Console.WriteLine(cpt++.ToString()); cpt = 0; Console.WriteLine((++cpt).ToString()); Console.ReadLine(); } – Sebastien Feb 18 '11 at 09:30
  • Hm... My brain has lagged... I didn't understand you told about the execution flow. I shloud have written "The ToString() method is executed over the non incremented value" – Sebastien Feb 18 '11 at 09:41