Пост-приращение x на n (n!= 1)
Итак, если я выполнил следующий код...
int x = 0;
Debug.WriteLine(x++);
Debug.WriteLine(x += 4);
Debug.WriteLine(x);
... Я получаю 0, 5 и 5 соответственно. То, что я хотел бы получить, однако, это 0, 1 и 5. Есть ли способ сделать post-increment на n в С#? Или мне нужно написать + = как собственное выражение?
Просто для контекста, что я на самом деле делаю, это куча операций BitConverter в буфере, и было бы очень приятно, чтобы каждый из них был самодостаточным, где смещение увеличивается на величину тип данных, преобразованный в. Таким образом, если формат буфера будет позже изменен, я могу просто добавить или удалить одну строку, не беспокоясь о каком-либо окружающем коде.
Ответы
Ответ 1
Вы должны иметь возможность злоупотреблять Interlocked.Exchange, чтобы получить старое значение переменной и в то же время заменить его значение:
Debug.WriteLine(Interlocked.Exchange(ref x, x+4));
замените значение переменной x
на x + 4
, но вернем предыдущее значение x
.
Edit:
Демонстрация показывает, что это "увеличение на 4 и своп" выполняется в 4-х инструкциях - никакого вызова вообще не требуется, поэтому производительность должна быть хорошей:
Interlocked.Exchange(ref x, x + 4);
0000005e mov eax,dword ptr [rbp+2Ch]
00000061 add eax,4
00000064 xchg eax,dword ptr [rbp+2Ch]
00000067 mov dword ptr [rbp+28h],eax
неинтуитивный характер этого (и других) решений, вероятно, сводится к нарушению Принцип CQS - мы мутируем переменную и возвращаем значение сразу, то есть не то, что мы должны делать в основном потоке.
Ответ 2
Насколько я знаю, это невозможно. Вы можете написать свой метод обертки следующим образом:
static void ExecuteWithPost(ref int value, Action<int> operation, Func<int, int> postOperation)
{
operation(value);
value = postOperation(value);
}
и используйте его:
int i = 0;
ExecuteWithPost(ref i, x => Debug.WriteLine(x), x => x + 1);
ExecuteWithPost(ref i, x => Debug.WriteLine(x), x => x + 4);
ExecuteWithPost(ref i, x => Debug.WriteLine(x), x => x);
Распечатывает то, что вы хотите.
Метод обертки может быть общим, чтобы заставить его работать с типами, отличными от int
:
static void ExecuteWithPost<T>(ref T value, Action<T> operation, Func<T, T> postOperation)
{
operation(value);
value = postOperation(value);
}
Ответ 3
Оператор ++
- это короткая форма x = x + 1;
, поэтому использование +=
- неплохая идея:
Если я правильно вас понимаю:
int x = 0;
Debug.WriteLine(x++); //return 0
Debug.WriteLine(x); //return 1
Debug.WriteLine(x += 4); //return 5
Я предлагаю вам использовать оператор +=
, потому что любой другой способ перегрузки оператора или что-то еще; будет просто накладными расходами.