关于 dotnet/运行时的实现细节



最近,我很高兴阅读了corefx的部分内容(最近移至dotnet/runtime repo(。我遇到了Array.CopyTo方法:

public static void Copy(Array sourceArray, long sourceIndex, Array destinationArray, long destinationIndex, long length)
{
int isourceIndex = (int)sourceIndex;
int idestinationIndex = (int)destinationIndex;
int ilength = (int)length;
if (sourceIndex != isourceIndex)
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.sourceIndex, ExceptionResource.ArgumentOutOfRange_HugeArrayNotSupported);
if (destinationIndex != idestinationIndex)
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.destinationIndex, ExceptionResource.ArgumentOutOfRange_HugeArrayNotSupported);
if (length != ilength)
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length, ExceptionResource.ArgumentOutOfRange_HugeArrayNotSupported);
Copy(sourceArray, isourceIndex, destinationArray, idestinationIndex, ilength);
}

引起我注意的是,该方法将long参数转换为int(意味着它丢弃了 MSB(,并将它们与实际参数进行比较,如果它们不相等,则抛出异常。我看到的是,当且仅当这些long参数中的任何一个大于 int 时,才会抛出异常。最大值或小于整数。最小值。问题是,为什么这些论点从一开始就long?为什么不让他们int.

只有Microsoft才能明确回答"为什么?"的问题。可是。。。

提供这种方法以及其他类似的方法是为了方便。在某些情况下,可能有一个表示要复制的数组中的区域的long值。例如,使用非托管内存,稍后逐个复制到托管阵列。

如果没有这样的重载,调用方将不得不做同样的工作才能获得相同的安全程度,并且很可能会错误地做到这一点(例如,只转换值而不检查溢出(。

通过提供long参数重载,该框架既方便又能更好地抵抗客户端代码错误。这样,客户端仍然可以在适当的时候使用long值,并将它们直接传递给框架 API,而无需做额外的工作来正确隐藏它们。

这样做的原因是API将其定义为支持大范围的值,但此实现不支持复制"巨大数组",因此它会引发异常。API 中没有定义不应支持"巨型数组",它只是实现。其他实现可能支持 long 可以定义的任何数组大小,或者可以更改此实现以支持它。如果类型为 int,则需要进行重大 API 更改。

无论如何,.NET API 通常都会处理带有长整型的长度和大小,因此无需更改它,而是需要巨大的值。

最新更新