I know there are a lot of answers, and an accepted one, but I'll still put in my two cents for yet another point of view.
I know this question was C#, but I assume that for something like a postfix operator it doesn't have different behavior than C:
int main(){
int x = 0;
while (x<1)
x = x++;
}
The assembly (yes, I edited it to make it more readable) generated by the compiler shows
...
mov -8(rbp), 0 ; x = 0
L1:
cmp -8(rbp), 1 ; if x >= 1,
jge L2 ; leave the loop
mov eax, -8(rbp) ; t1 = x
mov ecx, eax ; t2 = t1
add ecx, 1 ; t2 = t2 + 1
mov -8(rbp), ecx ; x = t2 (so x = x + 1 !)
mov -8(rbp), eax ; x = t1 (kidding, it's the original value again)
jmp L1
L2:
...
Equivalently, the loop is doing something like:
t = x
x = x + 1
x = t
Side note: turning on any optimizations gives you some assembly result like this:
...
L1:
jmp L1
...
it doesn't even bother to store the value you told it to give x!