今天我很震惊,有意比较Buffer.BlockCopyArray.CopyTo.的内在性格。我很好奇,看看Array.CopyTo是否在后台调用了Buffer.BlockCopy。这背后没有实际目的,我只是想进一步了解C#语言及其实现方式。不要急着指责我进行微优化,但是您可以指责我好奇!

当我在mscorlib.dll上运行ILdasm时,我收到的是Array.CopyTo

.method public hidebysig newslot virtual final
    instance void  CopyTo(class System.Array 'array',
                          int32 index) cil managed
{
  // Code size       0 (0x0)
} // end of method Array::CopyTo


这对于Buffer.BlockCopy

.method public hidebysig static void  BlockCopy(class System.Array src,
                                            int32 srcOffset,
                                            class System.Array dst,
                                            int32 dstOffset,
                                            int32 count) cil managed internalcall
{
  .custom instance void System.Security.SecuritySafeCriticalAttribute::.ctor() = ( 01 00 00 00 )
} // end of method Buffer::BlockCopy


坦白说,这让我感到困惑。我从未在未创建的dll / exe上运行ILdasm。这是否意味着我将看不到这些功能的实现方式?搜索仅显示a stackoverflow question,这是Marc Gravell所说的


  [Buffer.BlockCopy]基本上是原始内存副本的包装


虽然很有见地,但Array.CopyTo是否调用Buffer.BlockCopy并不能回答我的问题。我特别感兴趣的是,我是否能够看到这两个函数的实现方式,以及将来是否对C#的内部结构有疑问,是否有可能进行研究。还是我不走运?

最佳答案

这里最大的问题是,根据发布的内容,您正在查看参考程序集,尤其是.NET 4的参考程序集。它们是特殊的程序集,它们的所有IL都被删除,仅包含元数据。这是.NET 4中的新增功能,它解决了.NET早期版本中的一个旧问题。如果参考程序集只是GAC中安装的实际程序集的副本。

这造成了麻烦,在以后的版本和服务包中对更改程序进行了更改。特别是WaitHandle.WaitOne(int)重载是众所周知的,它是在.NET 3.0(又名.NET 2.0 SP1)中添加的。程序员不经意间发现,重载heckofalot比神秘的WaitOne(int,bool)重载更容易使用。但是存在一个问题,即他们的程序将不再在原始.NET 2.0发行版上运行,从而产生MissingMethodException。

通常,添加此重载是一件很顽皮的事情,他们修改了mscorlib.dll,但没有更改其[AssemblyVersion]。通过在.NET 4中提供单独的参考程序集,此问题不再发生。 Microsoft现在可以在不破坏任何内容的情况下修改.NET类型的公共接口。这样做是出于意料,一些.NET 4中间版本在没有人注意的情况下进行了流式传输。

因此,请确保反汇编mscorlib.dll的实际版本(GAC中的版本)。 NET 4的哪个存储在不同的目录c:\ windows \ microsoft.net \ assembly中,而不是c:\ windows \ assembly中。资源管理器外壳名称空间扩展不再保护该扩展名,您只需使用File + Open即可浏览GAC目录。您将在C:\ Windows \ Microsoft.NET \ assembly \ GAC_32 \ mscorlib \ v4.0_4.0.0.0__b77a5c561934e089目录中找到32位版本。

事情还没完结,当您深入研究时,会发现Array.CopyTo()调用了一个名为[Array.Copy()]的内部帮助器方法,该方法具有[MethodImpl(MethodImplOptions.InternalCall)]属性。同样,没有方法主体。该属性告诉即时编译器该方法实际上是在CLR内部以C ++实现的。请参见this answer以了解如何查看此类方法的源代码。

07-28 02:40
查看更多