views:

73

answers:

2

When I Tried to return a Array in VFP9 languaje COM/DLL to my .net c# project I received a System.Object[*] array and I can not cast to System.Object[] (Without asterisk).

+3  A: 

Unfortunately, you cannot cast it directly. You can, however, create a new array of type object[] and copy the data over. Something like...

Array sourceArray = ...;

if (sourceArray.Rank != 1)
    throw new InvalidOperationException("Expected a single-rank array.");

object[] newArray = new object[sourceArray.Length];
Array.Copy(sourceArray, sourceArray.GetLowerBound(0),
           newArray, 0, sourceArray.Length);
Timwi
Great, this works, but if you have thousands of items, you think?'ll Keep testing with queries or grades.
Cheva
googling I find a VFP instruction for this from VFP source code: the function ComArray(This.newArray, 10) that pass to based zero. the inverse method
Cheva
+4  A: 

Timwi's solution should work fine. You can do something a bit simpler using Linq:

object[] newArray = sourceArray.Cast<object>().ToArray();

In case you need to recreate a System.Object[*] to pass it back to VFP, you can use this overload of the Array.CreateInstance method:

public static Array CreateInstance(
    Type elementType,
    int[] lengths,
    int[] lowerBounds
)

You can use it as follows:

object[] normalArray = ...

// create array with lower bound of 1
Array arrayStartingAt1 =
    Array.CreateInstance(
        typeof(object),
        new[] { normalArray.Length },
        new[] { 1 });

Array.Copy(normalArray, 0, arrayStartingAt1, 1, normalArray.Length);
Thomas Levesque
Somehow I never think of the solutions which are shorter but much slower. I realise that in most cases the performance penalty is insignificant...
Timwi
Does this work because the `Cast` can simply iterate over the array using an IEnumerator instead of worrying where the array starts? If so couldn't you just use `Select(x => x).ToArray()` (or even just`ToArray()` ) instead? It would remove the need for a cast from `object` to `object`.
Callum Rogers
Indeed, it will be a bit slower. When the source sequence implements `ICollection<T>`, `ToArray` takes advantage of that, but arrays with non-zero bounds only implements the non-generic `ICollection`...
Thomas Levesque
@Callum Rogers, yes, exactly. `Array` implements `IEnumerable`
Thomas Levesque
You MASTER!. Thank you very much!
Cheva
@Myself: You can't just use `ToArray()` or `Select()` because `Array` only implements the non-generic `IEnumerable` and they both require `IEnumerable<T>`. +1 for this answer for cleverness.
Callum Rogers