There are various reasons why .NET Reflector might fail to decompile a particular method, generate source that does not match the original source code, or generate source code that will not compile without some modifications being made. I’ve listed some of these reasons here, so, in no particular order:
- The code has been obfuscated. Generally if this is a matter of type/member renaming then .NET Reflector will decompile the code without complaining, but it may not be possible to compile the code if the renaming resulted in members of different types being assigned the same name, which is perfectly legal in IL, but not in C# or VB, or if the obfuscated member names include Unicode non-printable characters, which is again perfectly legal within IL. If control flow obfuscation has been applied then .NET Reflector may completely fail to decompile the method because the obfuscated IL will look nothing like the IL that is generated as output from any of the .NET framework compilers. This makes it impossible for .NET Reflector, in its current form, to infer the original source code.
- The compiled IL could be decompiled to more than one source code construct with equivalent functionality. Different source code constructs, e.g., switch statements and if statements, can often be compiled to very similar IL. Under these circumstances it can be difficult for .NET Reflector to determine the original source construct, and so it may pick the wrong one during decompilation.
- The IL may have been compiled from a declarative language, such as F#. In this case, if you try to decompile to an OO/procedural language, such as C# or VB, you’re likely to run into problems because the compiled IL again won’t look anything like that output by either of the C# or VB compilers.
- You haven’t selected the correct .NET Framework optimisation in View > Options. If you’re decompiling code written with .NET 3.5 you should switch to the .NET 3.5 optimisation in the Disassembler pane in the Options dialog. All you need to do is select .NET 3.5 from the Optimization drop-down. By default, .NET Reflector tries to generate source code targetting .NET 2.0.
- You’re trying to decompile .NET 4.0 code. We haven’t released a version of .NET Reflector that includes .NET 4.0 support yet so there are bound to be problems. We’ll be adding some level of support for .NET 4.0 in the next major release of .NET Reflector, which ideally will be available in early 2010.
- The method you’re trying to decompile is an unmanaged method called using P/Invoke. Please see below.
On the last point, .NET Reflector cannot decompile unmanaged code (please see http://www.simple-talk.com/community/blogs/bart/archive/2009/07/31/74218.aspx), so any methods accessed via P/Invoke won’t be decompiled. These methods are defined outside of your assembly in unmanaged code, and in some cases, in the framework class libraries, these methods are implemented by the CLR itself. See figures 1 – 4 for examples.
Figure 1. Typical P/Invoke signature in disassembler view showing DllImport attribute on method declaration describing library in which method is defined (C# output).
Figure 2. P/Invoke signature for same method shown in figure 1, but using VB output.
Figure 3. P/Invoke signature for method implemented internally by the CLR (C# output). Note the use of the MethodImpl attribute with MethodImplOptions.InternalCall, which indicates that the method is implemented by the CLR. This cannot be used from user code.
If none of the above applies, then the last thing I’ll say is that .NET Reflector’s decompilation support isn’t perfect. However, we are working to improve it, so please do tell us when things go wrong so we can look at fixing them.
Note that if .NET Reflector is unable to decompile the source you can still view the IL. Please see this post for instructions: