C# 如何从Array.ConstrainedCopy获取InvalidCastException
下面是讨论的示例代码(考虑爬行动物是“动物”,哺乳动物也是“动物”)C# 如何从Array.ConstrainedCopy获取InvalidCastException,c#,.net,arrays,C#,.net,Arrays,下面是讨论的示例代码(考虑爬行动物是“动物”,哺乳动物也是“动物”) Animal[]爬行动物=新爬行动物[] {新爬行动物(“蜥蜴”)、新爬行动物(“蛇”)}; 动物[]动物=新动物[] {新爬行动物(“鳄鱼”)、新哺乳动物(“海豚”)}; 尝试 { 数组.ConstrainedCopy(动物,0,爬行动物,0,2); } 捕获(ArrayTypeMismatchException atme) { Console.WriteLine(“[”+String.Join我看到这个方法也会抛出一个In
Animal[]爬行动物=新爬行动物[]
{新爬行动物(“蜥蜴”)、新爬行动物(“蛇”)};
动物[]动物=新动物[]
{新爬行动物(“鳄鱼”)、新哺乳动物(“海豚”)};
尝试
{
数组.ConstrainedCopy(动物,0,爬行动物,0,2);
}
捕获(ArrayTypeMismatchException atme)
{
Console.WriteLine(“[”+String.Join我看到这个方法也会抛出一个InvalidCastException
。抛出InvalidCastException
的条件是:
sourceArray中至少有一个元素不能强制转换为
命中注定
所以我被难住了,如果这种方法声明永远不能对数组元素进行任何强制转换,那么如何从中获得InvalidCastException?老实说,我认为这只是一个复制粘贴错误;他们只是忘记了将其从异常列表中删除。下面的代码在Mono 2.10.2.0上抛出了InvalidCastException
(而问题中的代码不适用)。不过,文档中的解释并不适合这种情况
Animal[] reptiles = new Reptile[]
{ new Reptile("lizard"), new Reptile("snake") };
object[] animals = new object[]
{ new Reptile("alligator"), new Mammal("dolphin") };
try
{
Array.ConstrainedCopy(animals, 0, reptiles, 0, 2);
}
catch (ArrayTypeMismatchException atme)
{
//Console.WriteLine('[' + String.Join<Animal>(", ", reptiles) + ']');
}
Animal[]爬行动物=新爬行动物[]
{新爬行动物(“蜥蜴”)、新爬行动物(“蛇”)};
对象[]动物=新对象[]
{新爬行动物(“鳄鱼”)、新哺乳动物(“海豚”)};
尝试
{
数组.ConstrainedCopy(动物,0,爬行动物,0,2);
}
捕获(ArrayTypeMismatchException atme)
{
//Console.WriteLine('['+String.Join(“,”,爬行动物)+']');
}
来自(备注部分):
sourceArray类型必须与destinationArray类型相同或派生自destinationArray类型;否则,将引发ArrayTypeMismatchException
在您的示例中,动物
数组类型与爬行动物
数组类型不相同,也不派生自爬行动物(动物
不是爬行动物
)。这就是引发数组类型不匹配激发的原因
根据上述条件和您示例中的异常消息,可以得出结论,在调用Array.ConstrainedCopy
方法时,无法获得InvalidCastException
。这是文档中的一个错误。我偷偷看了一眼Array
类,在那里我看到了Array.containedcpy()
只在内部调用Array.Copy()
而不进行任何类型验证,其中作为CLR方法Array.Copy()实际上可以抛出InvalidCastException
:
(摘自MSDN)
从引用类型或值类型数组复制到对象数组时,将创建一个对象
来保存每个值或引用,然后进行复制。当从对象
数组复制到引用类型或值类型数组且无法进行赋值时,将抛出一个InvalidCastException
我假设Array.Copy()
只是将InvalidCastException
提升到Array.ConstrainedCopy()
,所以从技术上讲,Array.ConstrainedCopy()
抛出一个InvalidCastException
,尽管它不应该按照定义抛出。堆中第一个数组的实际类型是爬虫[]
Animal[] reptiles = new Reptile[] { ... };
//IL_0002: newarr Reptile
第二个阵列:
Animal[] animals = new Animal[] { ... };
// IL_0025: newarr Animal
没有从爬行动物[]到动物[]的投射。
因此,这是Array.ConstrainedCopy()方法的正确行为
此代码将正常工作:
Animal[] reptiles = new Animal[] { new Reptile("lizard"), new Reptile("snake") };
Animal[] animals = new Animal[] { new Reptile("alligator"), new Mammal("dolphin") };
如果无法访问Array.Copy的实际本机实现,我们可能只能检查。以下是clr\src\vm\comsystem.cpp中的相关代码行:
FCIMPL6(void, SystemNative::ArrayCopy, ArrayBase* m_pSrc, INT32 m_iSrcIndex, ArrayBase* m_pDst, INT32 m_iDstIndex, INT32 m_iLength, CLR_BOOL reliable)
{
// ...
r = CanAssignArrayTypeNoGC(gc.pSrc, gc.pDst);
if (r == AssignWrongType) {
// [Throw ArrayTypeMismatchException]
}
if (r == AssignWillWork) {
// [Copy the array using memmove, which won't throw any exception]
return;
}
else if (reliable) {
// [Throw ArrayTypeMismatchException]
}
// [Handle other cases]
}
当Array.ConstrainedCopy
调用SystemNative::ArrayCopy
并将reliable
参数设置为TRUE
时,要么使用memmove
复制数组,要么抛出ArrayTypeMismatchException
。在任何情况下都不会抛出InvalidCastException
。nedCopy的实现与Array.Copy相同,除了一个ReliabilityContractAttribute
之外,如果我们在IL反汇编程序中打开ConstrainedCopy,我们会看到它所做的一切就是将其参数加载到堆栈中,并将其传递给Array.Copy。
正如异常状态所述,Array.ConstrainedCopy
在某些情况下抛出异常,而Array.Copy不抛出异常。
ConstrainedCopy
在复制数组之前验证数组。
示例:regular Array.Copy方法将以静默方式将字节数组复制到int数组。Array.ConstrainedCopy方法将引发异常。这可以提高可靠性。
class Program
{
static void Main()
{
byte[] original = new byte[10];
original[0] = 1;
int[] destination = new int[10];
// This will work if you call Array.Copy instead.
Array.ConstrainedCopy(original, 0, destination, 0, original.Length);
}
}
顺便说一句:
Array.ConstrainedCopy不允许进行加宽转换
结论:
Array.ConstrainedCopy方法不允许某些副本。它比Array.Copy更具辨别力。它还引发异常。通常,ConstrainedCopy不是必需的
关于问题的答案:
System.InvalidCastException:是可通过调用Array.Copy引发的异常之一,
由于Array.ConstrainedCopy正在调用Array.Copy,记录Array.ConstrainedCopy抛出系统.InvalidCastException的指定是正确的,但由于验证的优先级,我们将永远不会看到InvalidCastException,但是。这是一个很好的问题。遗憾的是,该方法最终是在CLR中实现的,看起来不是这样可能会使用类似reflector的东西来回答这个问题。希望了解此方法的人能够看到并回答…我怀疑被调用的基础方法有一个名为可靠的
的参数,我假设该参数与所做的保证有关。我怀疑基础方法可能抛出InvalidCastEx异常
,但当可靠
参数如本例中所示为真时则不例外。可靠
在使用基本复制命令时为假(因此在
class Program
{
static void Main()
{
byte[] original = new byte[10];
original[0] = 1;
int[] destination = new int[10];
// This will work if you call Array.Copy instead.
Array.ConstrainedCopy(original, 0, destination, 0, original.Length);
}
}