Here is the sample code for the discussion (consider Reptile "is a" Animal and Mammal "is a" Animal too)
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) + ']');
}
When I run this code I get a ArrayTypeMismatchException, with as comment
Array.ConstrainedCopy will only work on array types that are provably compatible, without any form of boxing, unboxing, widening, or casting of each array element. Change the array types (i.e., copy a Derived[] to a Base[]), or use a mitigation strategy in the CER for Array.Copy's less powerful reliability contract, such as cloning the array or throwing away the potentially corrupt destination array.
However when I look at MSDN I see this method also throws an InvalidCastException
. The condition for throwing an InvalidCastException
is:
At least one element in sourceArray cannot be cast to the type of destinationArray.
So I am stumped, how do you get an InvalidCastException out of this method, if as it states there can never be any casting of an array element?
Without access to the actual native implementation of Array.Copy
, the best we can probably do is examine the Shared Source CLI. Here are the relevant lines of code from 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]
}
When Array.ConstrainedCopy
calls SystemNative::ArrayCopy
with the reliable
parameter set to TRUE
, either the array is copied using memmove
or ArrayTypeMismatchException
is thrown. In neither case will InvalidCastException
be thrown.
Honestly, I think it's just a copy-paste typo; they just forgot to remove it from the list of exceptions.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With