tzippy tzippy - 1 year ago 66
C# Question

Copy array of one type to array of different type

I was wondering if it's possible to use some sort of Array.Copy method in C# to copy elements of one array to and array of same size but different type.
I get a struct from a native c++ library that contains a pointer to Integer and a size element. These integer values represent enum Values from enum

Foo
.
At the moment I'm using a for loop. Is there a better/safer approach?
Thanks!

Using
Array.Copy
throws an
ArrayTypeMismatchException
as shown below:

using System;

public class Program
{
public enum Foo
{
FOO_1,
FOO_2
}

public static void Main(string[] args)
{
int nCount = 1;
Foo[] fooArr = new Foo[nCount];
Int32[] RawData = new Int32[nCount];
RawData[0] = 100;
Array.Copy(RawData, fooArr, nCount);
}
}

Answer Source

For some reason, neither Array.Copy nor Buffer.BlockCopy is happy to copy from an int[] to a Foo[], although Array.Copy can go in the other direction perfectly happily.

It looks to me like your options are:

  • The kind of copy you showed in your original post, although I'd write it as:

    for (int i = 0; i < RawData.Length; i++)
    {
        fooArr[i] = RawData[i];
    }
    

    .. that way you don't have a redundant variable outside the scope of the loop

  • A LINQ-based approach as suggested by Romano ZumbĂ©, although in that case you shouldn't create the array beforehand as well
  • A LINQ-like-but-not-LINQ approach using Array.ConvertAll:

    var fooArr = Array.ConvertAll(RawData, x => (Foo) x);
    

    ... this is more efficient than the LINQ approach as it can create an array of the correct size to start with.

  • If you don't need the execution-time type to actually be Foo[], you can just cast without any copying... because the CLR is happy to treat an int[] as a Foo[]:

    Foo[] fooArr = (Foo[]) (object) RawData;
    

    At that point, you have a single array object, which you're viewing as either an int[] (via RawData) or a Foo[] (via fooArr). Changes via either variable will be visible in the other variable. This is clearly very efficient, but could lead to problems elsewhere depending on how you use fooArr. If you just use it in foreach loops or via regular index accesses, it would be fine.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download