3

I have an object parameter that is being called via COM interop and the type of the object coming in is System.Byte[*] and I want to get it to a byte[]; is there a way to do this without copying?

Both an explicit cast and the as keyword both fail. The odd thing is that both of those methods work how I want in the 'Immediate' window if I break in my function.

public void DoIt(object param) {
    var bbuf = param as byte[];
    // bbuf is NULL here

    bbuf = (byte[])param;
    // Throws cast exception

    // This works, but I don't want to copy
    var abuf = param as Array;
    bbuf = new byte[abuf.Length];
    abuf.CopyTo(bbuf, 0);
}
joshperry
  • 41,167
  • 16
  • 88
  • 103
  • Where do you see `System.Byte[*]`? Is that just something you see in the debugger? Does it actually show a `*` or is that just a placeholder for something else, e.g. `System.Byte[28]`? – p.s.w.g Nov 13 '13 at 21:37
  • 4
    `System.Byte[*]` is an array that has a non-zero lower bound. For example, an array that starts at 1. – Daniel A.A. Pelsmaeker Nov 13 '13 at 21:38
  • @p.s.w.g `param.GetType().ToString()` and also the cast exception shows `System.Byte[*]`. – joshperry Nov 13 '13 at 21:39
  • @Virtlink ah! beautiful. The array comes from FoxPro (which is 1-based) so that makes total sense. I guess copying is my only recourse then to get a zero-based array. Add and answer and I'll accept it. – joshperry Nov 13 '13 at 21:40

1 Answers1

8

The type byte[*] is a non-zero-lower-bound single-dimensional array. For example, an array with a lower bound of 1. Normal single-dimensional arrays are zero-based (SZ-arrays). Seems to me the only course of action is to copy it:

public static T[] ToSZArray<T>(Array array)
{
    T[] dest = new T[array.Length];
    Array.Copy(array, dest, array.Length);
    return dest;
}

(Full code)

Unfortunately I couldn't find any MSDN documentation on byte[*]. The only thing I know is that the byte[*] name is used to highlight the difference between it and an SZ-array byte[]. The latter has special support and instructions in the CLI.


Example usage:

// Create an array string[1..4]
var arr = Array.CreateInstance(typeof(string),
    lengths: new[] { 4 },
    lowerBounds: new[] { 1 });

// Some values.
arr.SetValue("1", 1);
arr.SetValue("2", 2);
arr.SetValue("3", 3);
arr.SetValue("4", 4);

// The conversion to an SZ-array.
string[] dest = ToSZArray<string>(arr);
Daniel A.A. Pelsmaeker
  • 47,471
  • 20
  • 111
  • 157
  • 1
    Never seen a `[*]` array before, do you have a link to any MSDN documentation? – Scott Chamberlain Nov 13 '13 at 21:46
  • @ScottChamberlain I didn't even know .NET supported that. I found [this thread](http://social.msdn.microsoft.com/Forums/vstudio/en-US/c9691757-5a26-431b-8888-a1db1e40cfda/cnonzero-lower-bound-arrays?forum=netfxbcl) on the MSDN forums discussing it. – p.s.w.g Nov 13 '13 at 21:47
  • Great generic function! Thanks for the code. Any thoughts on what would be the best way to verify that the array is homogenous? – joshperry Nov 13 '13 at 21:49
  • @joshperry With homogeneous, do you mean to verify that all elements have the same type? – Daniel A.A. Pelsmaeker Nov 13 '13 at 21:55
  • @joshperry You can see the type of elements in any array by using `array.GetType().GetElementType()`. In your case, this will return the `System.Byte` type. Perhaps that will help? – Daniel A.A. Pelsmaeker Nov 13 '13 at 22:05