如何从Array.ConstrainedCopy获取InvalidCastException

Mis*_*hax 19 .net c# arrays

以下是讨论的示例代码(考虑爬虫"是"动物和哺乳动物"是"动物也是如此")

Animal[] reptiles = new Reptile[] 
    { new Reptile("lizard"), new Reptile("snake") };

Animal[] animals = new Animal[]
    { new Reptile("alligator"), new Mammal("dolphin") };

try
{
  Array.ConstrainedCopy(animals, 0, reptiles, 0, 2);
}
catch (ArrayTypeMismatchException atme)
{
  Console.WriteLine('[' + String.Join<Animal>(", ", reptiles) + ']');
}
Run Code Online (Sandbox Code Playgroud)

当我运行此代码时,我得到一个ArrayTypeMismatchException,带有注释

Array.ConstrainedCopy仅适用于可证明兼容的数组类型,不会对每个数组元素进行任何形式的装箱,拆箱,加宽或转换.更改数组类型(即,将Derived []复制到Base []),或者在CER for Array.Copy不太强大的可靠性契约中使用缓解策略,例如克隆数组或丢弃可能损坏的目标数组.

但是,当我看到MSDN时,我看到这个方法也引发了一个问题InvalidCastException.投掷的条件InvalidCastException是:

sourceArray中至少有一个元素无法强制转换为destinationArray类型.

所以,我很为难,怎么你得到一个InvalidCastException了这种方法,如果因为它规定永远不会有一个数组元素的任何铸造?

Mic*_*Liu 7

如果无法访问实际的本机实现Array.Copy,我们可以做的最好的事情就是检查共享源CLI.以下是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]
}
Run Code Online (Sandbox Code Playgroud)

当参数设置为的Array.ConstrainedCopy调用SystemNative::ArrayCopy时,无论是使用还是抛出数组.在任何情况下都不会被抛出.reliableTRUEmemmoveArrayTypeMismatchExceptionInvalidCastException