Search code examples
.netildasm

Where to go to view System.Collections.Generic IL code in ildasm?


My curiosity piqued by this question, I went in search of the implementation of List.Clear(). When I ran ildasm on System.Collections.dll like so:

cd c:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETCore\v4.5
"C:\Program Files (x86)\Microsoft SDKs\Windows\v8.1A\bin\NETFX 4.5.1 Tools\ildasm.exe" System.Collections.dll

and looked at System.Collections.Generic.List`1::Clear : void(), this is what I found:

.method public hidebysig newslot virtual final 
         instance void  Clear() cil managed
{
  // Code size       1 (0x1)
  .maxstack  8
  IL_0000:  ret
} // end of method List`1::Clear

That's not what I'm looking for.

I'm aware that some .NET dll's are a level of indirection so that different versions of the framework can be directed to. If that's the case here, how do I figure out where the actual code is? Or if there is something else going on, tips on how to go about using ildasm for this kind of task are appreciated. I'm more capable at using ildasm for looking at my own stuff, but am not experienced at using it to examine framework code.

Update

Using Hans' pointer in the right direction I ended up doing the following:

cd C:\Windows\Microsoft.NET\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089
"C:\Program Files (x86)\Microsoft SDKs\Windows\v8.1A\bin\NETFX 4.5.1 Tools\ildasm.exe" mscorlib.dll

This lead me to the following for the Clear() method on System.Collections.Generic.List`1::Clear : void():

.method public hidebysig newslot virtual final 
        instance void  Clear() cil managed
{
  .custom instance void __DynamicallyInvokableAttribute::.ctor() = ( 01 00 00 00 ) 
  // Code size       49 (0x31)
  .maxstack  8
  IL_0000:  ldarg.0
  IL_0001:  ldfld      int32 class System.Collections.Generic.List`1<!T>::_size
  IL_0006:  ldc.i4.0
  IL_0007:  ble.s      IL_0022
  IL_0009:  ldarg.0
  IL_000a:  ldfld      !0[] class System.Collections.Generic.List`1<!T>::_items
  IL_000f:  ldc.i4.0
  IL_0010:  ldarg.0
  IL_0011:  ldfld      int32 class System.Collections.Generic.List`1<!T>::_size
  IL_0016:  call       void System.Array::Clear(class System.Array,
                                                int32,
                                                int32)
  IL_001b:  ldarg.0
  IL_001c:  ldc.i4.0
  IL_001d:  stfld      int32 class System.Collections.Generic.List`1<!T>::_size
  IL_0022:  ldarg.0
  IL_0023:  dup
  IL_0024:  ldfld      int32 class System.Collections.Generic.List`1<!T>::_version
  IL_0029:  ldc.i4.1
  IL_002a:  add
  IL_002b:  stfld      int32 class System.Collections.Generic.List`1<!T>::_version
  IL_0030:  ret
} // end of method List`1::Clear

So that led me to look at System.Array::Clear(), which gave me:

.method public hidebysig static void  Clear(class System.Array 'array',
                                            int32 index,
                                            int32 length) cil managed internalcall
{
  .custom instance void System.Security.SecuritySafeCriticalAttribute::.ctor() = ( 01 00 00 00 ) 
  .custom instance void System.Runtime.ConstrainedExecution.ReliabilityContractAttribute::.ctor(valuetype System.Runtime.ConstrainedExecution.Consistency,
                                                                                                valuetype System.Runtime.ConstrainedExecution.Cer) = ( 01 00 03 00 00 00 02 00 00 00 00 00 ) 
  .custom instance void __DynamicallyInvokableAttribute::.ctor() = ( 01 00 00 00 ) 
} // end of method Array::Clear

which is another bit of a dead-end, but at least I now know where to go for this kind of info.


Solution

  • The reference assemblies in .NET 4+ are special, they only contain metadata and all the IL bodies were stripped. Pretty important to allow them to be used to target platforms that are very different from the Windows desktop and to support PCL. The actual code in them does not matter at all, the compiler only uses the metadata.

    Also keep in mind the mismatch between reference assemblies and runtime assemblies, many of the reference assemblies just contain [TypeForwardedTo] to target the specific runtime assembly that the platform provides.

    If you want to peek at the code then you'll need to look at the actual runtime assemblies. They are easy to get to for the desktop, you can navigate to c:\windows\microsoft.net\assembly directly. I used an old machine to copy the .NET 4.0 versions. Silverlight is easy as well, just navigate to its install directory. You can get the Phone ones from the emulator by opening the .vhd file. Probably also works for WindowsRT, never tried it. Forget about XBox.