System.ArrayTypeMismatchException
The exception that is thrown when an attempt is made to store an element of the wrong type within an array.
Minimum version: >= 1.1 >= Core 1.0
Statistics
How to handle it
try
{
}
catch (System.ArrayTypeMismatchException e)
{
}
try
{
}
catch (System.ArrayTypeMismatchException e) when (e.Message.Contains("something"))
{
}
try
{
}
catch (System.ArrayTypeMismatchException e) when (LogException(e))
{
}
private static bool LogException(Exception e)
{
logger.LogError(...);
return false;
}
How to avoid it
We haven't written anything about avoiding this exception yet. Got a good tip on how to avoid throwing System.ArrayTypeMismatchException? Feel free to reach out through the support widget in the lower right corner with your suggestions.
Links
YouTube videos
Possible fixes from StackOverflow
Okay, this really depends on a few oddities combined:
Even though in C# you can't cast a
byte[]
to ansbyte[]
directly, the CLR allows it:var foo = new byte[] {246, 127}; // This produces a warning at compile-time, and the C# compiler "optimizes" // to the constant "false" Console.WriteLine(foo is sbyte[]); object x = foo; // Using object fools the C# compiler into really consulting the CLR... which // allows the conversion, so this prints True Console.WriteLine(x is sbyte[]);
Cast<T>()
optimizes such that if it thinks it doesn't need to do anything (via anis
check like the above) it returns the original reference - so that's happening here.ToList()
delegates to the constructor ofList<T>
taking anIEnumerable<T>
That constructor is optimized for
ICollection<T>
to useCopyTo
... and that's what's failing. Here's a version which has no method calls other thanCopyTo
:object bytes = new byte[] { 246, 127 }; // This succeeds... ICollection<sbyte> list = (ICollection<sbyte>) bytes; sbyte[] array = new sbyte[2]; list.CopyTo(array, 0);
Now if you use a Select
at any point, you don't end up with an ICollection<T>
, so it goes through the legitimate (for the CLR) byte
/sbyte
conversion for each element, rather than trying to use the array implementation of CopyTo
.
UPDATED WITH THE SOLUTION
Okay, this was very tricky. I have no idea how you manage to get this type of project. You might have upgraded your project type from an earlier version of ASP.NET MVC. Any way below is the answer.
In you Web.Config's runtime Assembly binding section, please add the below.
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0-5.0.0.0" newVersion="5.0.0.0" />
</dependentAssembly>
This should fix your problem.
You can use .Select(e => (Test)e)
.
You are trying to cast the array to int[]
when it is a uint[]
. That by itself is fine, since both int[]
and uint[]
are of type Array
, and casting an Array object of type uint[]
as an int[]
(or vice versa) is allowed (for some reason).
The problem comes when you try to then convert it to a List. The method is trying to create a List of type int
because that's the type you specified, but that's not what the type of the array actually is.
assembly.GetTypes()
returns a RuntimeType[]
, but it uses array type covariance to disguise it as a Type[]
. Per the docs for the Span
constructor, an ArrayTypeMismatchException
is thrown if T
(which in this case is Type
) does not match the runtime array type (which in this case is RuntimeType
).
assembly.GetTypes().ToArray()
on the other hand returns an actual Type[]
: it will create a brand new array based on the declared type T
, which is Type
, so you get a true Type[]
array and there is no mismatch -- T
is Type
and you're passing a true Type[]
to the Span
constructor.
ReadOnlySpan<T>
does not have this constraint, since it is not possible to write an incompatible Type
to a read-only RuntimeType[]
, so you can do this:
new ReadOnlySpan<Type>(assembly.GetTypes());
Source: Stack Overflow