Hello,
why the next example throws a System.ArrayTypeMismatchException?
New Int16(){4,5,6}.Cast(of UInt16).ToArray()
I expected that this line returned a UInt16 array containing 4,5 and 6.
Thanks in advance.
Hello,
why the next example throws a System.ArrayTypeMismatchException?
New Int16(){4,5,6}.Cast(of UInt16).ToArray()
I expected that this line returned a UInt16 array containing 4,5 and 6.
Thanks in advance.
Because Int16 and UInt16 are different types. You could try this:
New Int16() {4, 5, 6}.Select(Function(x) CType(x, UInt16)).ToArray()
This is a bug in Cast or ToArray, IMO. The code in this answer is in C#, but hopefully you can see what it's about :)
I believe that Cast first tries to see if a simple reference conversion will work - i.e. where it can return the same reference back.
For example:
String x = "hello";
IEnumerable<char> y = x.Cast<char>();
Console.WriteLine(object.ReferenceEquals(x, y)); // Prints true
Unfortunately, it does this using the CLR rules for compatibility - under which UInt16[] and Int16[] are compatible. That leads to this happening:
short[] array = new short[]{4, 5, 6};
IEnumerable<ushort> cast = array.Cast<ushort>();
Console.WriteLine(object.ReferenceEquals(array, cast)); // Prints True
Unfortunately if you then try to call ToArray(), it's not happy:
// Explicit type argument just for clarity
cast.ToArray<ushort>(); // Bang
ToArray no doubt tries to do some optimisation - which fails in this particular case because the type isn't what it really expects it to be.
I believe the correct behaviour should be for Cast to return a lazy iterator, but for that to fail when it executes later. That's what happens if you try to go from Int16 to Int32, for example.
Now, to get back to what you really want to do: use a Select call instead. Cast is only meant to be for unboxing operations and reference type conversions.