4

This gem was created in some interop code which we decompiled. We can't figure out how to create an instance of this array, nor what type of array it is.

Looking at Type.GetElementType gives me that it is an array of type Double, but we can't figure out how it is different from System.Double[].

Aron
  • 15,464
  • 3
  • 31
  • 64
  • There is no difference. All arrays are implicitly derived from **Array**. In C++/CLI you even declare it as array^. – Ulugbek Umirov Apr 17 '14 at 06:20
  • @UlugbekUmirov There *is* a difference - `double[]` is far stricter than "an array of double". Saying there's no difference is like saying that an array of double is no different from an array of string, because they're both arrays. Both are derived from `Array`, but they're not the same type. – Luaan Feb 09 '17 at 12:14

1 Answers1

15

This is a typical interop problem, the array was created in a COM Automation server. Which exposes the array as a SafeArray, the CLR automatically marshals them to a .NET array object and maintains its structure as specified in the safe array descriptor.

A System.Double[] array is a very specific kind of array in the CLR, it is a "vector array" which has its first element at index 0. These kind of arrays are heavily optimized in the CLR.

The trouble with the array you got is that it has one dimension, like a vector array, but does not have its first element at index 0. Common if you interop with code written in Visual Basic or FoxPro for example. Such code often likes to start the array at index 1. Could be anything however.

C# does not have syntax sugar to access such an array, you cannot use the [] operator to index the array. You have to use the members of the Array class, ploddingly. So:

  • Array.GetLowerBound(0) tells you where to start indexing the array
  • Array.GetUpperBound(0) tells you how far to go
  • Read an element from the array with Array.GetValue(index)

Could be easier to just copy the array:

public static double[] ConvertDoubleArray(Array arr) {
    if (arr.Rank != 1) throw new ArgumentException();
    var retval = new double[arr.GetLength(0)];
    for (int ix = arr.GetLowerBound(0); ix <= arr.GetUpperBound(0); ++ix)
        retval[ix - arr.GetLowerBound(0)] = (double)arr.GetValue(ix);
    return retval;
}
Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536