На самом деле это многошаговый процесс. Все, что вы получите от DLL или EXE - это байт-код IL, который по сути является абстрактным машинным языком. Этот байт-код IL может быть преобразован один в один в язык ассемблера IL (например, с помощью ILDASM или режима прямого IL Reflector).
Режим декомпилятора языка C # в Reflector продвигается дальше и выбирает структуру из кода, который напоминает циклы if
/ else
, while
, операторы switch и т. Д., И переводит его в соответствующие операторы. Информация о именах локальных переменных не сохраняется в IL, поэтому она должна составлять их по мере продвижения; Кроме того, некоторые управляющие структуры могли быть оптимизированы до неузнаваемости, что приводит к созданию операторов goto
. Есть также некоторые конструкции, которые не имеют прямых параллелей в языке C #, поэтому вы можете найти неофициальные ключевые слова расширения, такие как methodof
в декомпилированном коде.
Интересным упражнением является изучение того, как переводится более новый код C # при декомпиляции в более ранние версии языка. Например, понимания запросов LINQ переводятся как цепочки методов через IEnumerable<T>
, а лямбда-выражения, переданные в аргументы Expression<T>
, заменяются целой связкой goo для построения и передачи абстрактного синтаксического дерева, соответствующего лямбда-выражению, что фактически во что такие конструкции переводятся компилятором.