[C#/.NET] Как корректно перегрузить оператор ++ для структурного типа?

agaaaa

public static StructType operator++(StructType value)
{
StructType result = value;
value.m_value++;
return result;
}

Такой код, само собой, работает не так, как надо. Потому что параметр value передаётся по значению и в итоге не изменяется. Как реализовать поведение, аналогичное Int32?

Dasar

написать ref?

agaaaa

это очевидное решение я уже пробовал

Dasar

убери создание StructType внутри operator-а

struct X2
{
int i;
public static X2 operator ++(X2 x)
{
x.i++;
return x;
}
public override string ToString
{
return i.ToString;
}
}
[MTAThread]
static void Main(string[] args)
{
X2 x = new X2;
X2 y = x++;
X2 z = ++x;

Console.WriteLine(x);
Console.WriteLine(y);
Console.WriteLine(z);

int _x = new int;
int _y = _x++;
int _z = ++_x;

Console.WriteLine(_x);
Console.WriteLine(_y);
Console.WriteLine(_z);

return;
}

выдает

2
0
2
2
0
2

agaaaa

Хм... а в MSDN я это не нашёл. Дьявол!

6yrop

по-моему все в соответствии с основными принципами value type-ов, что еще надо писать?

agaaaa

Вообще говоря, value должен был передаваться по значению. Или компилятор просто как-то специально извращается, чтобы такая штука работала. Я себе это так представляю: принимается аргумент операции, копируется в стек (для типа-значения должен, для ссылки само собой копируется указатель затем вышеприведённый код инкрементирует скопированное значение и возвращает его. Видимо компилятор считает operator++ эквивалентом a = a++;
Кстати, либо нужно пройтись по проекту профайлером, либо JIT компилятор в дотнете вовсе не темный: описал структуру Native - тип-оболочку для машинно-зависимого целого. В тесте на 1ккк операций инкремента этот тип медленнее предопределённых int и long примерно в 4,5 раза.
UPD: АЕ! Это 600-ое сообщение!

Dasar

Вообще говоря, value должен был передаваться по значению. Или компилятор просто как-то специально извращается, чтобы такая штука работала
http://msdn2.microsoft.com/en-us/library/aa691363%28VS.71%29...
The run-time processing of a postfix increment or decrement operation of the form x++ or x-- consists of the following steps:
If x is classified as a variable:
x is evaluated to produce the variable.
The value of x is saved.
The selected operator is invoked with the saved value of x as its argument.
The value returned by the operator is stored in the location given by the evaluation of x.
The saved value of x becomes the result of the operation.
http://msdn2.microsoft.com/en-us/library/aa691369%28VS.71%29...
The run-time processing of a prefix increment or decrement operation of the form ++x or --x consists of the following steps
If x is classified as a variable:
x is evaluated to produce the variable.
The selected operator is invoked with the value of x as its argument.
The value returned by the operator is stored in the location given by the evaluation of x.
The value returned by the operator becomes the result of the operation

Dasar

и соответственно запись public static X2 operator ++(X2 x)
трактуется как public static X2 operator ++(ref X2 x)

agaaaa

Ну не совсем же так...

Dasar

совсем

Dasar

да, не прав, все нормально работает и без ref.

Dasar

y=++x транслируется в

x = f(x);
y = x;

а y=x++ транслируется в

oldx = x;
x = f(x);
y = oldx;

6yrop

Да. Reflector в твоем примере показывает вот
 

private static void Main(string[] args)
{
X2 x1 = new X2;
X2 x = X2.op_Increment(x1);
X2 y = x1;
X2 z = x = X2.op_Increment(x);
Console.WriteLine(x);
Console.WriteLine(y);
Console.WriteLine(z);
int _x = 0;
int _y = _x++;
int _z = ++_x;
Console.WriteLine(_x);
Console.WriteLine(_y);
Console.WriteLine(_z);
}






2All, спасибо, теперь я больше знаю про С#

agaaaa

Остался один вопрос - как написать класс для работы с машинно-зависимыми целыми, чтоб он не уступал int и long в скорости?..

bleyman

Блиин, тут же рядом только что был длинный тред на тему извращений с генериками. Там ссылки были даже.

agaaaa

Это который?
Оставить комментарий
Имя или ник:
Комментарий: