去哪里查看 ildasm 中的 System.Collections.Generic IL 代码?

Posted

技术标签:

【中文标题】去哪里查看 ildasm 中的 System.Collections.Generic IL 代码?【英文标题】:Where to go to view System.Collections.Generic IL code in ildasm? 【发布时间】:2015-07-04 07:16:47 【问题描述】:

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

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

这不是我要找的。​​p>

我知道一些 .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

这又是一条死胡同,但至少我现在知道去哪里获取此类信息了。

【问题讨论】:

这不是一个完全的死胡同。为.NET Core 5 调用的Here is the native CLR 代码。它不是 .NET Framework,但我敢打赌它会非常接近。如果你想要 2.0 CLR 的源代码,你可以得到它here 另外如果你不了解,一定要看看referencesource.microsoft.com,虽然不像看IL那样“具体细节”,但应该还算准确。 @ScottChamberlain,非常感谢。你们的两个cmets都给我指出了我不知道的地方。 【参考方案1】:

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

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

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

【讨论】:

谢谢你,@hanspassant。当我需要查看 System.Array.Clear() 时,我陷入了死胡同,正如您在问题中的更新中看到的那样。对此有任何指示吗?即,去哪里获取 System.Array.Clear() 的代码?【参考方案2】:

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

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

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

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

您可能可以使用免费的反编译器(例如 ILspy 或 DotPeek)执行类似的操作,但它们不会连接到 LinqPad,因此您需要确定要打开哪个 dll。

【讨论】:

谢谢,+1。没有 Linqpad 或 Reflector,但这很有帮助,因为我认为我需要其中一个或两个。将 Hans 的答案标记为它,只是因为它引导我到了需要 ildasm 的地方,但是谢谢!

以上是关于去哪里查看 ildasm 中的 System.Collections.Generic IL 代码?的主要内容,如果未能解决你的问题,请参考以下文章

ILDASM 的安装使用

ildasm 引用第三方 DLL 中的内部类

vs2008下如何打开ildasm反编译器

VS2010如何打开ildasm反编译器?

使用 ildasm 检测 WPF 程序集之间的标记差异

在VS里配置及查看IL