Пост-приращение 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

Я предлагаю вам использовать оператор +=, потому что любой другой способ перегрузки оператора или что-то еще; будет просто накладными расходами.