Постинкремент x на n (n!= 1)

Итак, если я выполню следующий код...

int x = 0;
Debug.WriteLine(x++);
Debug.WriteLine(x += 4);
Debug.WriteLine(x);

... получаю 0, 5 и 5 соответственно. Однако я бы хотел получить 0, 1 и 5. Есть ли способ сделать постинкремент на n в C#? Или я должен написать += как собственное утверждение?

Просто для контекста то, что я на самом деле делаю, это набор операций BitConverter над буфером, и было бы очень хорошо иметь каждую из них в качестве самодостаточного оператора, где смещение увеличивается на размер типа данных, являющихся конвертировано в. Таким образом, если формат буфера будет позже изменен, я могу просто добавить или удалить одну строку, не беспокоясь ни о каком окружающем коде.

3 ответа

Решение

Вы должны иметь возможность злоупотреблять Interlocked.Exchange, чтобы получить старое значение переменной и в то же время заменить ее значение:

Debug.WriteLine(Interlocked.Exchange(ref x, x+4));

другими словами, замените значение переменной x с x + 4 но вернуть предыдущее значение x,

Редактировать:

Разборка показывает, что это "увеличение на 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 - мы изменяем переменную и возвращаем значение сразу, т.е. не то, что мы должны делать в основном потоке.

Насколько я знаю, это невозможно. Вы можете написать свой метод-обертку так:

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);
}

Оператор ++ это короткая форма x = x + 1; так используя += неплохая идея

Если я вас правильно понимаю

int x = 0;
Debug.WriteLine(x++);  //return 0
Debug.WriteLine(x);  //return 1
Debug.WriteLine(x += 4);  //return 5

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

Другие вопросы по тегам