Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/327.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
可以检查核心C#功能的内部_C#_Implementation_Il_Mscorlib - Fatal编程技术网

可以检查核心C#功能的内部

可以检查核心C#功能的内部,c#,implementation,il,mscorlib,C#,Implementation,Il,Mscorlib,我今天很惊讶,我倾向于比较Buffer.BlockCopy和Array.CopyTo.的内部结构。我很好奇Array.CopyTo是否在幕后被称为Buffer.BlockCopy。这背后没有任何实际目的,我只是想进一步了解C#语言及其实现方式。别急着指责我的微优化,但你可以指责我好奇 当我在mscorlib.dll上运行ILdasm时,我为Array.CopyTo .method public hidebysig newslot virtual final instance void

我今天很惊讶,我倾向于比较
Buffer.BlockCopy
Array.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。这是否意味着我无法看到这些函数是如何实现的?四处搜索才发现,马克·格雷威尔说

[
Buffer.BlockCopy
]基本上是原始mem副本上的包装器

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

是一个免费的.NET反编译器。您可以使用它来检查任何.NET DLL,包括mscorlib


Array.CopyTo
调用
Array.Copy
Array.Copy
Buffer.BlockCopy
都是
extern
方法,这意味着它们是在本机代码中定义的,而不是在托管的.NET代码中定义的,因此我无法再告诉您它们是如何工作的。

当我使用Telerik JustDecompile on Buffer.BlockCopy时,我发现:

[SecuritySafeCritical]
public static extern void BlockCopy(Array src, int srcOffset, Array dst, int dstOffset, int count);
这意味着它不是用产生IL代码的东西实现的

和Array.CopyTo:

public void CopyTo(Array array, int index) {
  if (array != null && array.Rank != 1) {
    throw new ArgumentException(Environment.GetResourceString("Arg_RankMultiDimNotSupported"));
  }
  Array.Copy(this, this.GetLowerBound(0), array, index, this.Length);
}
数组。复制显示:

[SecuritySafeCritical]
[ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
public static void Copy(Array sourceArray, int sourceIndex, Array destinationArray, int destinationIndex, int length) {
  Array.Copy(sourceArray, sourceIndex, destinationArray, destinationIndex, length, false);
}
超载:

[SecurityCritical]
[ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
internal static extern void Copy(Array sourceArray, int sourceIndex, Array destinationArray, int destinationIndex, int length, bool reliable);
所以这也不是IL代码


如果您想检查这些方法,必须拿出反汇编程序。

这里最大的问题是,从您发布的内容来看,您正在查看参考程序集,尤其是.NET 4的参考程序集。它们是特殊的程序集,所有的IL都已剥离,只包含元数据。这在.NET4中是新的,它解决了.NET早期版本中的一个旧问题。其中,参考程序集只是安装在GAC中的实际程序集的副本

这造成了麻烦,在后来的版本中进行了更改,服务包破坏了程序。尤其是WaitHandle.WaitOne(int)重载臭名昭著,它是在.NET3.0(又名.NET2.0SP1)中添加的。程序员无意中发现重载一个heckoffalot比神秘的WaitOne(int,bool)重载更容易使用。但问题是他们的程序将不再在最初的.NET2.0发行版上运行,从而产生MissingMethodException

添加此重载通常是一件非常棘手的事情,他们修改了mscorlib.dll,但没有更改其[AssemblyVersion]。通过在.NET 4中提供单独的引用程序集,此问题将不再发生。Microsoft现在可以修改.NET类型的公共接口,而无需中断任何操作。而且,有几个.NET4中间版本在没有人注意到的情况下发布了

因此,请务必反汇编mscorlib.dll的真实版本,即GAC中的版本。对于.NET 4,它存储在不同的目录中,即c:\windows\microsoft.NET\assembly,而不是c:\windows\assembly。它不再受explorershell名称空间扩展的保护,您可以简单地使用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++实现的。请参阅以了解如何查看此类方法的源代码。

使用pseudo属性(最终)实现了
Array.CopyTo
Buffer.BlockCopy

[MethodImpl(MethodImplOptions.InternalCall)]

如果你看看《聪明人将军》史蒂文·图布(Steven Toub)提出的第二个问题,这是一个非常好的解释。

我将回答我自己的问题。我意识到这是一种糟糕的风格,但如果不是因为之前的答案提供给我的精彩资源,我不可能制定出答案。多谢各位

首先,那些来到这里想知道如何检查C#函数内部的人,Tim发布了一个很棒的资源。这适用于没有外部定义方法的情况。当它们被外部定义时,似乎获得答案的唯一希望是下载。因为这是针对.Net 2.0而不是4.0的,所以我提供的信息可能是过时的。然而,我将继续假设所讨论的方法没有太大变化。在查看了源文件之后,我相信我可以回答以下问题:“Array.CopyTo是否在幕后调用Buffer.BlockCopy?”

在我进入问题的核心之前,其他人已经指出CopyTo调用Array.Copy。Copy是外部定义的,所以我将把我的查询改为“Array.Copy是否在幕后调用Buffer.BlockCopy?”我发现有趣的一点是

如果未明确要求实现System.Collections.ICollection,请使用[Array.]Copy以避免额外的间接寻址

让我区分要执行的每个函数必须为真的检查类型:

区块复制:

  • 目标和源不能为空
  • 目的地和目的地