Теперь я сделаю то, что не должно быть сделано ... Я попытаюсь упростить то, что написал здесь Эрик Липперт В чем разница между i ++ и ++ i? Надеюсь, я 'я не пишу слишком много неправильно: -)
Теперь ... Что делают операторы предварительного увеличения и последующего увеличения?Упрощение и игнорирование всей промежуточной копии (и помнить, что они не являются атомарными операторами в многопоточных средах):
оба они являются выражениями (например, i + 1
) которые возвращают результат (например, i + 1
), но имеют побочный эффект (в отличие от i + 1
).Побочным эффектом является то, что они увеличивают переменную i
.Большой вопрос "в каком порядке все происходит?"Ответ довольно прост:
- предварительное увеличение
++i
: увеличивает i
и возвращает новое значение i
- после увеличения
i++
: увеличивает i
и возвращает старое значение i
Сейчас ... Важная часть заключается в том, что increments i
всегда происходит первым.Затем возвращается значение (старое или новое).
Давайте создадим пример (пример Липперта довольно сложный. Я приведу другой, более простой пример, который не настолько завершен)но этого достаточно, чтобы проверить, верен ли порядок, о котором я говорил ранее, или нет) (технически я приведу два примера)
Пример 1:
unchecked
{
int i = Int32.MaxValue;
Console.WriteLine("Hello! I'm trying to do my work here {0}", i++);
Console.WriteLine("Work done {1}", i);
}
Пример 2:
checked
{
int i = Int32.MaxValue;
Console.WriteLine("Hello! I'm trying to do my work here {0}", i++);
Console.WriteLine("Work done {1}", i);
}
checked
означает, что в случае переполнения будет сгенерировано исключение (OverflowException
).unchecked
означает, что та же операция не вызовет исключения.Int32.MaxValue + 1
обязательно переполнится.С checked
будет исключение, с unchecked
i
станет -1.
Давайте попробуем запустить первый фрагмент кода.Результат:
Hello! I'm trying to do my work here 2147483647
Work done -1
Хорошо ... i
был увеличен, но Console.WriteLine
получил старое значение (Int32.MaxValue == 2147483647
).Из этого примера мы не можем определить порядок постинкремента и вызова Console.WriteLine
.
Давайте попробуем запустить второй фрагмент кода.Результат:
System.OverflowException: Arithmetic operation resulted in an overflow.
Хорошо ... Совершенно очевидно, что сначала было выполнено постинкрементное выполнение, вызвало исключение, а затем явно не было выполнено Console.WriteLine
(поскольку программа завершилась).
Итак, мы знаем, что приказ, который я сказал, правильный.
Сейчас.Чему вы должны научиться на этом примере?То же самое я узнал много лет назад.Приращения до и после в C и C # хороши для запутанных конкурсов кода.Они не годятся для многих других вещей (но обратите внимание, что C ++ отличается!).Из этого урока я узнал, что есть ровно два места, где вы можете свободно использовать постинкремент, и есть ровно ноль мест, где вы можете свободно использовать постинкремент.
«Безопасный» постинкремент
for (int i = 0; i < x; i++)
и
i++; // Written alone. Nothing else on the same line but a comment if necessary.
Предварительное увеличение "Safe"
(nothing)