0

From this post (and not only) we got to the point that the ++ operator cannot be applied on expressions returning value. And it's really obvious that 5++ is better to write as 5 + 1. I just want to summarize the whole thing around the increment/decrement operator. So let's go through these snippets of code that could be helpful to somebody stuck with the ++ first time at least.

// Literal
int x = 0++; // Error

// Constant
const int Y = 1;
double f = Y++; // error. makes sense, constants are not variables actually.

int z = AddFoo()++; // Error

Summary: ++ works for variables, properties (through a synthetic sugar) and indexers(the same).
Now the interest part - any literal expressions are optimized in CSC and, hence when we write, say

int g = 5 + 1; // This is compiled to 6 in IL as one could expect.
IL_0001: ldc.i4.6 // Pushes the integer value of 6 onto the evaluation stack as an int32.

For 5++ doesn't mean 5 becomes 6, it could be a shorthand for 5 + 1, like for x++ = x + 1 What's the real reason behind this restriction?

int p = Foo()++ //? yes you increase the return value of Foo() with 1, what's wrong with that?

Examples of code that can lead to logical issues are appreciated.

One of real-life example could be, perform one more actions than in the array.

for (int i = 0; i < GetCount()++; i++) { }

Maybe the lack of usage opts compiler teams to avoid similar features? I don't insist this is a feature we lack of, just want to understand the dark side of this for compiler writers perhaps, though I'm not. But I know c++ allows this when returning a reference in the method. I'm neither a c++ guy(very poor knowledge) just want to get the real gist of the restriction. Like, is it just because c# guys opted to restrict the ++ over value expressions or there are definite cases leading to unpredictable results?

Arman
  • 5,136
  • 3
  • 34
  • 36

2 Answers2

2

In order for a feature to be worth supporting, it really needs to be useful. The code you've presented is in every case less readable than the alternative, which is just to use the normal binary addition operator. For example:

for (int i = 0; i < GetCount() + 1; i++) { }

I'm all in favour of the language team preventing you from writing unreadable code when in every case where you could do it, there's a simpler alternative.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Jon, this is indeed a good point for feature selection. Then (i++ vs i += 1), do you think the ++/-- operators were chosen for C# as a language feature mostly as a tribute to history of the c/c++ world (where for ex. getcount()++ is a possible case)? Say, if you were inventing a brand new language today would you add this operator for variables as in C# now? – Arman Jan 21 '13 at 19:58
  • @Arman: I would *probably* still include `i++` and `++i`, yes. They're convenient enough and useful enough to merit inclusion, but I *don't* think I'd want to include `get_count()++`. I just don't think it's a good thing to be able to do. – Jon Skeet Jan 21 '13 at 20:03
  • Jon, 'probably' - a very little but doubt :) OK, I'm actually happy with this feature as most developers, just wanted to know the opinion of language/compiler professional. Wouldn't be bad in contrast to have a nice feature in C# , like x# which would increase floating numbers by half, like in musical notation a semitone does :). Thanks for the reply. – Arman Jan 21 '13 at 20:13
0

Well before using these operators you should try to read up on how they do what they do. In particular you should understand the difference between postfix and prefix, which could help figure out what is and isn't allowed.

The ++ and -- operators modify their operands. Which means that the operand must be modifiable. If you can assign a value to the expression in question then it is modifiable, and is probably a variable(c#).

Taking a look at what these operators actually do. The postfix operators should increment after your line of code executes. As for the prefix operators, well they would need to have access to the value before the method had even been called yet. The way I read the syntax is ++lvalue (or ++variable) converting to memory operations:[read, write, read] or for lvalue++ [read, read, write] Though many compilers probably optimize secondary reads.

So looking at foo()++; the value is going to be plopped dead in the center of executing code. Which would mean the compiler would need to save the value somewhere more long-term in order for operations to be performed on said value, after the line of code has finished executing. Which is no doubt the exact reason C++ does not support this syntax either.

If you were to be returning a reference the compiler wouldn't have any trouble with the postfix. Of course in C# value types (ie. int, char, float, etc) cannot be passed by reference as they are value types.

Josh C
  • 1,035
  • 2
  • 14
  • 27