'vb.net Source array type cannot be assigned to destination array type on Enum

I've had to update a vb.net project from .NetFramework 4 to .NetFramework 4.7.2. In the process the following code is now throwing an error

Dim actuatorModelsArr = DirectCast(retNumberList, Array) Dim
Dim actuatorModels = actuatorModelsArr.Cast(Of ACTUATORMODELS)().ToList()

The error is System.ArrayTypeMismatchException: Source array type cannot be assigned to destination array type.

retNumberList is an Integer array ACTUATORMODELS is an Enum

in the .netFramework 4 version actuatorModels is a list of the Enum {System.Collections.Generic.List`1[FisherIECLib.ACTUATORMODELS]}

The list is used later in the module via linq to grab one of the Enums as a return value.

Is there a way around this or a way to create a list of the Enum?

Thanks in advance, Hank



Solution 1:[1]

djv's answer helps fix your problem. Hopefully this answer will explain what's going wrong. If you look at the reference source for Cast(Of T) on an untyped IEnumerable, you'll find that the first thing that happens is the C# equivalent of this:

Dim asTyped = TryCast(source, IEnumerable(Of TResult))
If asTyped IsNot Nothing Then Return asTyped

Surprisingly, this cast will work for Integer() to IEnumerable(Of ACTUATORMODELS). This sets the issue in motion, because when it comes to making a List(Of T) out of the resulting sequence, it turns out that Integer() and ACTUATORMODELS() are actually not interchangeable, but Cast has already treated the sequence as though they are.

Based on some testing, this issue seems to arise out of the interaction of this corner case with a corner case in how the List(Of T) range constructor works and the more general corner case of Integer() vs TEnum().

In the general case of iterating over Integer() as if it were IEnumerable(Of TEnum), it works. You can make a For Each loop over the sequence, the enumeration variable will have TEnum as the type, and you'll see the values as if they were TEnum.

The problem comes in the range constructor for List(Of T), and an optimization there for a source that implements ICollection(Of T). In that case, the ctor will try to use ICollection(Of T).CopyTo to copy the items into the list's internal storage. This is where the error ultimately occurs, because (going back to the implementation of Cast(Of T)) the source is still the Integer() array, and Array.Copy (via Array.CopyTo) is not OK with trying to do that with a destination of TEnum().

I feel like this is a bug somewhere, though I'm not sure if it's in Cast(Of T), the List(Of T) range ctor, or in the array copy handling. I'm also not sure it's something that will get fixed, since it's a corner case that hits what look like significant optimizations and would require a very specialized check to catch.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Craig