Проблемы с компиляцией некоторого декомпилированного кода C#

Я декомпилировал проект с открытым исходным кодом (потому что исходный код последней версии еще не выпущен). Используя инструмент RedGate Reflector, он дал мне этот блок кода:

if(somecondition == true)
{
    ref Vector3i vectoriRef;
    float num17 = length - num;
    Vector3i end = vectori3;
    (vectoriRef = (Vector3i) &end)[1] = vectoriRef[1] - ((int) num17);
}

somecondition — логическое значение. length и num — это числа с плавающей запятой, определенные вне кода. vectori3 также определяется вне кода и имеет тип Vector3i. Тип Vector3i по существу является этим кодом, но с сохраненными значениями x, y и z. как целые числа.

Когда я пытаюсь скомпилировать этот декомпилированный код, я получаю следующие ошибки:

  • Строка 2: В качестве оператора могут использоваться только выражения присваивания, вызова, увеличения, уменьшения и нового объекта.
  • Строка 3: ; ожидал
  • Строка 3: неверный термин выражения 'ref'
  • Строка 6: «Vector3i» — это «тип», но используется как «переменная».

Любые мысли о том, как я могу исправить этот код, чтобы он правильно компилировался и делал то, для чего он был предназначен?

ОБНОВЛЕНИЕ: оказалось, что исходный код есть в их репозитории, но чтобы найти его, вам нужно пройти по лабиринту ссылок и подсказок. Спасибо всем, кто опубликовал!


person Colin O'Dell    schedule 24.12.2010    source источник
comment
Есть ли причина, по которой вы не можете просто дождаться выхода исходного кода?   -  person Bernard    schedule 24.12.2010
comment
Вы уверены, что у вас есть выбор С#?   -  person Bryan    schedule 24.12.2010
comment
@Bernard - Сопровождающим проекта требуется вечность, чтобы выпустить исходный код. @ Брайан - Да.   -  person Colin O'Dell    schedule 24.12.2010


Ответы (2)


На первый взгляд

if (somecondition)
{
    vectori3[1] -= (int)(length - num);
}

Мне не совсем понятен синтаксис явных ссылок - я никогда раньше этого не видел и не могу заставить VS принять его, но последняя строка разбивается на

vectoriRef = (Vector3i) &end;
vectoriRef[1] = vectoriRef[1] - ((int) num17);
person Rup    schedule 24.12.2010
comment
Спасибо, объяснение имеет смысл и, кажется, соответствует остальной части функции :) - person Colin O'Dell; 24.12.2010

В коде используется изменяемый тип значения, что является «худшей практикой» в C#. Код, который мы генерируем для изменяемых типов значений, может быть довольно сложным для правильного анализа и декомпиляции; видимо вы столкнулись с ошибкой в ​​движке декомпиляции. C# не поддерживает данный синтаксис. (Это возможно в будущем; я написал прототип «ref locals», и он работает довольно хорошо, но неясно, действительно ли эта функция достаточно ценна для клиентов, чтобы гарантировать полную разработку и реализацию.)

Внимательно прочтите код, и вы увидите, что он делает: он создает копию vectori3 в end, затем получает ссылку на end (помните, "this" при вызове типа значения всегда является ссылкой на переменную, потому что вызов может изменять содержимое этой переменной.) Затем он использует ссылку для изменения переменной. Но почему? Этот код не имеет никакого смысла. Зачем создавать локальную копию переменной, затем изменять копию, а затем удалять измененную копию?

Я подозреваю, что вы не только нашли ошибку в декомпиляторе; возможно, вы также нашли ошибку в коде.

person Eric Lippert    schedule 24.12.2010
comment
Неизменяемые типы значений также не являются хорошей практикой в ​​некоторых случаях. Я показал здесь, как неизменяемые типы значений не обязательно являются потокобезопасными stackoverflow.com/questions/370859/. Но есть и другая сторона медали: в XNA интенсивно используются изменяемые типы значений (векторы, матрицы и т. д.) из-за соображений производительности, и эти типы данных были разработаны таким образом при участии Рико Мариани, и он объяснил, почему ( blogs.msdn.com/b/ricom/archive/ 07.09.2006/745085.aspx). - person Pop Catalin; 24.12.2010
comment
Ехать по скользкой дороге со скоростью 100 миль в час — худшая практика? Ну, это зависит от того, если вы пытаетесь выиграть ралли, то это не так, иначе это определенно так. - person Pop Catalin; 24.12.2010
comment
@Pop: Ваш пример небезопасного для потоков неизменяемого типа значения изменяет переменную. Не имеет значения, является ли тип значения неизменным или нет; переменные по определению изменяемы. Кроме того, в вашем примере даже не требуется многопоточность, чтобы проиллюстрировать, что это может измениться в неизменяемом типе значения; потоки — отвлекающий маневр. Код в том же потоке, будь то синхронный или асинхронный, может изменить значение this. Помните: это всегда переменная в типе значения, а переменные различаются. - person Eric Lippert; 25.12.2010
comment
@Pop: Конечно, иногда использование изменяемого типа значения оправдано. Но эта практика настолько опасна и потенциально сбивает с толку, что оправдание должно быть действительно хорошим. В случае с XNA выбор изменяемых векторов явно обусловлен тщательно измеренными реальными данными о производительности, основанными на пользовательском сценарии. Если у вас есть такие данные, чтобы оправдать создание изменяемого типа значения, отлично, сделайте это и задокументируйте, черт возьми, это решение. Если нет, то избегайте этой «худшей практики», как чумы. - person Eric Lippert; 25.12.2010