在ildasm中查看System.Collections.Generic IL代码的位置?

时间:2015-04-25 17:43:01

标签: .net ildasm

我的好奇心被question激怒了,我去寻找List.Clear()的实现。当我在ildasm上运行System.Collections.dll时,就像这样:

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

并查看System.Collections.Generic.List`1::Clear : void(),这是我发现的:

.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

这不是我想要的。

我知道某些.NET dll是一个间接级别,因此可以指向不同版本的框架。如果是这种情况,我如何找出实际代码的位置?或者,如果还有其他事情发生,那么有关如何使用ildasm进行此类任务的提示表示赞赏。我更有能力使用ildasm来查看自己的内容,但是没有经验使用它来检查框架代码。

更新

使用Hans'指针朝着正确的方向我最终做了以下事情:

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

这引导我对System.Collections.Generic.List`1::Clear : void()上的Clear()方法进行了以下操作:

.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

所以这让我看了System.Array::Clear(),它给了我:

.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

这是另一个死胡同,但至少我现在知道去哪里寻找这种信息。

2 个答案:

答案 0 :(得分:5)

.NET 4+中的引用程序集是特殊的,它们只包含元数据,并且所有IL主体都被剥离。让它们用于与Windows桌面非常不同的平台并支持PCL非常重要。它们中的实际代码根本不重要,编译器只使用元数据。

还要记住引用程序集和运行时程序集之间的不匹配,许多引用程序集只包含[TypeForwardedTo]以定位平台提供的特定运行时程序集。

如果要查看代码,那么您需要查看实际的运行时程序集。它们很容易进入桌面,您可以直接导航到c:\ windows \ microsoft.net \ assembly。我使用旧机器来复制.NET 4.0版本。 Silverlight也很简单,只需导航到其安​​装目录即可。您可以通过打开.vhd文件从模拟器中获取Phone。可能也适用于WindowsRT,从未尝试过。忘了XBox。

答案 1 :(得分:3)

有很多方法可以做到这一点,所以这只是我的方式,因为我碰巧有LinqPadReflector的副本。

我会打开LinqPad并写一个小脚本

var x = new List<String>();
x.Clear();

然后将鼠标移到Clear()上并按下Shift-F1,这将在正确的位置打开反射器并反编译Clear()。这使我不得不试图找出哪个dll包含实际代码。

你可以使用免费的反编译器(例如ILspy或DotPeek)做类似的事情,但是他们没有挂钩到LinqPad,所以你需要找出要打开的dll。