2016-09-20 6 views
0

Кто-то предоставил мне исходный код для их полезности, который мне нужен для обратной инженерии и замены. Есть много заданий в коде следующим образом:Есть ли священные знания, которые мне не хватает в C#, декомпилированных с помощью Telerik JustDecompile?

var a = checked(checked(checked((int)SomeArray.Length) - 1) + 1); 

Является ли это какой-то шаблон дизайна, что я не в курсе, или просто так, как декомпилирует

var a = SomeArray.Length; 
+0

Возможно, код был скомпилирован в проверенном контексте. Тем не менее я не знаю, что делает этот код. Операция длины массива в действии C# возвращает собственный int. Возможно, оригинальный автор пытался выяснить, подходит ли длина в int (что в значительной степени будет) –

+0

Но как насчет этой таинственной «-1 + 1» умственной акробатики? – ajeh

+1

Моя догадка заключается в том, что парень пытается проверить, может ли предмет вписаться в int и не во время компиляции. –

ответ

0

Вот что я думаю, что происходит ,

Это потому, что компилятор C# является «потерянным», поскольку компилятор C# вычисляет такие вещи, как преобразования типа данных, а затем выводит эти преобразования непосредственно в DLL, которую он пишет. Все библиотеки DLL написаны в CIL, что не так богато, как C#, поэтому сложные проверки и конструкции переведены на более, но более простые инструкции.

Например, C# имеет идею лямбда-функций, но CIL не делает этого, поэтому компилятор C# будет генерировать класс с помощью метода на нем, а затем вызвать этот метод. Например;

str => str.Length 

становится чем-то вроде

class DisplayClass234 
{ 
    public int Execute(string str) 
    { 
     return str.Length; 
    } 
} 

Итак, если вы пытаетесь декомпилировать, Telerik видит класс "DisplayClass234", а не оригинальный лямбда.

+0

Означает ли это, что это был оригинальный разработчик, который добавил и вычитал 1 во все длины массивов? – ajeh

+0

Мне кажется, что это артефакт компилятора; Я не вижу причин делать это так, если разработчик не убедится в чем-то сумасшедшем. Если у вас есть доступ к инструменту JustCompile, попробуйте написать небольшое консольное приложение всего за несколько операций, скомпилируйте его, затем декомпилируйте и посмотрите, появляется ли это в декомпилированном коде. Также попробуйте в свойствах проекта и, возможно, попробуйте проверить и снять флажок «разрешить небезопасный код» и «оптимизировать код», чтобы узнать, представили ли они странность. –

1

Я никогда не знал компилятора C#, чтобы испускать дополнительные арифметические инструкции при генерации кода для Array.Length. В IL, Array.Length выглядит примерно так:

ldloc.1 // Assuming an array was stored in local slot 1 
ldlen 

Даже в клетчатой ​​контексте, это то, что он выглядит. Теперь в IL нет такой вещи, как проверенный контекст, как в C#. IL имеет только различные арифметические инструкции, которые проверяются (например, add.ovf вместо add).

Если кто-то написал такой код:

int length = checked(array.Length - 1 + 1); 

код IL, который получает испускаемый выглядит примерно так:

ldloc.1 
ldlen 
conv.i4 
ldc.i4.1 
sub.ovf 
ldc.i4.1 
add.ovf 
stloc.2 

Это не удивило бы меня, если декомпилятор лечит каждый из тех *.ovf инструкции и инструкцию conv.i4 как имеющие свой проверенный контекст. Читая инструкции и постепенно создавая C# выражение бы получить что-то вроде следующего:

ldloc.1 // array 
ldlen  // array.Length 
conv.i4 // checked((int) array.Length) 
ldc.i4.1 
sub.ovf // checked(checked((int) array.Length) - 1) 
ldc.i4.1 
add.ovf // checked(checked(checked((int) array.Length) - 1) + 1) 
stloc.2 
0

Я не удивлюсь, если JustDecompile имеет ошибку, описанную Кайла. Я не могу вспомнить, какие запросы поддержки связаны с checked, так что часть кода на самом деле не провела хорошую проверку звука.

Скорее всего, если бы исходный код был checked(SomeArray.Length + 1 - 1), то компилятор отменил бы часть 1-1, поэтому он никогда не достигнет декомпилятора.

Почему бы вам не попросить IL этого заявления и разместить его здесь? Тот, кто декомпилировал это, должен также получить IL.