Необычные операторы С# в декомпилированном источнике...? - программирование

Необычные операторы С# в декомпилированном источнике...?

Я только что декомпилировал какой-то сторонний источник для отладки проблемы, используя DotPeek. Код вывода содержит некоторые необычные операторы, которые AFAIK недействительны С#, поэтому мне интересно, что они означают...

Экстракт выглядит (с комментариями Dotpeek, поскольку они, вероятно, актуальны);

protected internal void DoReceive(ref byte[] Buffer, int MaxSize, out int Written)
{
    Written = 0;
    .
    .
    .        
    // ISSUE: explicit reference operation
    // ISSUE: variable of a reference type
    int& local = @Written;
    int num = SomeMethod();
    .
    .
    .
    // ISSUE: explicit reference operation
    ^local = num;
}

Итак, 3 необычных оператора там... int& = @Written Кажется, присваивается указатель на переменную, которая называется бессмысленно с символом @?

Но что такое ^local = num;???

ОК, вот эквивалентный фрагмент от ILSpy, который имеет больше смысла, я думаю, что декомпиляция с С# не привела к действительному эквиваленту?

'С#'

 int& local = @Written;
 byte[] numArray2 = this.FInSpool;
 int num = (int) __Global.Min(numArray2 == null ? 0L : (long) numArray2.Length, (long) MaxSize);
 ^local = num;

IL

 byte[] expr_22 = this.FInSpool;
 Written = (int)__Global.Min((long)((expr_22 == null) ? 0 : expr_22.Length), (long)MaxSize);

Итак, я думаю, что "С#" не совсем допустимо? Этот IL был бы действительным С#, не зная, почему DotPeek произвел результат, который он сделал. Возможно, я буду придерживаться ILSpy для этого...?

4b9b3361

Ответ 1

Если вы посмотрите на raw IL (от ildasm, а не эквивалент С# через IL Spy), это может помочь вам понять, что пытается сказать декомпилятор. Параметры "Out" представлены с использованием (управляемой) типизированной ссылки, которая явно не отображается как тип в С#. "Экземпляры" этого типа обычно могут передаваться только как параметры методам, принимающим типизированные ссылки (параметры "ref" или "out" ). См. OpCodes.Mkrefany для получения дополнительной информации.

То, что dotPeek жалуется, заключается в том, что эта "введенная" ссылка была сохранена из аргумента в локальный слот переменной, а затем записывается позже через локальный слот. "@" И "^" - это заполнители, используемые для указания этого неожиданного поведения, обнаруженного декомпилятором (тот, который описываются комментариями ВОПРОСА.)

Возможно, код был скомпилирован из С++/CLI, и, следовательно, IL выглядит отличным от типичного вывода компилятора С#. Возможно, это и есть некоторый уровень незначительной запутывания, чтобы запутать декомпиляторы (хотя я так не думаю). Я не думаю, что это функционально не отличается от загрузки ссылки из ее аргумента в стек операций непосредственно (избегая использования локальный слот переменной), но я мог ошибаться.

Ответ 2

Помещая @ перед именем, вы можете использовать зарезервированное имя для переменной. Например, если бы я хотел иметь переменную с именем return, мне нужно было бы это сделать.

public int Weird()
{
    int @return = 0;
    return @return;
}

Подробнее см. этот вопрос.


Поместите ^ перед именем... umm, нет подсказки. (будет обновляться по мере того, как я исследую). Я мог бы найти любую информацию о том, что означает ^, когда он не используется как XOR)

Ответ 3

Это явно проблема декомпиляции. Из-за широкого набора поддерживаемых языков декомпилятор на какой-либо конкретный язык может не всегда находить точное совпадение, но все же пытается произвести некоторый вывод. Декомпилятор МОЖЕТ попробовать произвести несколько эквивалентный вывод, как в этом случае может быть:

protected internal void DoReceive(ref byte[] Buffer, int MaxSize, out int Written)
{
    Written = 0;
    .        
    int num = SomeMethod();
    .
    Written = num;
}

но СЛЕДУЕТ это действительно сделать? в этом случае декомпилятор действительно предоставил вам подсказку, чтобы вы могли решить, важно ли это для вашего конкретного случая, так как МОЖЕТ быть некоторыми побочными эффектами.