10

I have an object array and I want to convert it to a specific type array. I have the type to convert it into which I get at run time. But I am having a problem doing the actual conversion.

If I use the Convert.ChangeType, I get the error that Object must implement IConvertible

The Array.ConvertAll is template based and requires that I pass the destination type as a template which I only know at run time. I even tried to do use reflection to call this method but I cannot pass the lambda expression as an argument to the MethodInfo.Invoke method.

Any Ideas?

Right I have the following which is not working:

Type convertTo = GetFinalType();
Object[] objArr = GetObjectArray();
var arr = Array.ConvertAll(objArr,elem=> Convert.ChangeType(elem,convertTo));
John Saunders
  • 160,644
  • 26
  • 247
  • 397
shake
  • 1,752
  • 4
  • 18
  • 22
  • How is this "not working?" Is an exception thrown? – Mark Avenius Dec 02 '10 at 22:09
  • @Mark: *"I get the error that Object must implement IConvertible"* – cdhowie Dec 02 '10 at 22:11
  • The line var arr = Array.ConvertAll(objArr,elem=> Convert.ChangeType(elem,convertTo)); does not compile because it needs the target type as a template e.g Array.ConvertAll(objArr,elem=> Convert.ChangeType(elem,convertTo)); .. I only have T2 at runtime – shake Dec 02 '10 at 22:16
  • @shake: What kinds of objects are you storing in this array? – cdhowie Dec 02 '10 at 22:16
  • Its nothing special .. just a regular class object. I even tried (MyClass[])objArr and get the error {"Unable to cast object of type 'System.Object[]' to type 'MyClass[]'."} – shake Dec 02 '10 at 22:19
  • @shake in that case, I agree with the answer from @cdhowie. You need to implment this interface on any type with which you will be using this method. – Mark Avenius Dec 02 '10 at 22:19

5 Answers5

20

Have you tried this?

var finalType = GetFinalType();
var objArr = GetObjectArray();
var arr = Array.CreateInstance(finalType, objArr.Length);
Array.Copy(objArr, arr, objArr.Length);

That's untested, but it should work. It's more compact and doesn't (really) use reflection.

Doug
  • 5,208
  • 3
  • 29
  • 33
  • You are absolutely right. This is easier. Thanks for the comment. I should have thought of that a long time ago – shake Feb 01 '11 at 14:15
1

You are close; does the following work, or was objType a typo?

Type convertTo = GetFinalType();
Object[] objArr = GetObjectArray();
var arr = Array.ConvertAll(objArr,elem=> Convert.ChangeType(elem, convertTo));
Mark Avenius
  • 13,679
  • 6
  • 42
  • 50
1

I did it the worst way possible but I managed it somehow. I created a new class

public class Tools
{
    public static T[] Convert<T>(object[] objArr)
    {
        IList<T> list = new List<T>();

        foreach (var o in objArr)
        {
            list.Add((T)o);
        }

        return list.ToArray();
    }
}

And where I needed the conversion, I used:

MethodInfo method = typeof(Tools).GetMethod("Convert");
MethodInfo generic = method.MakeGenericMethod(new Type[] { t });

object o = generic.Invoke(null, new object[] { objArr });

var m =  Convert.ChangeType(o,typeof(tArr));

Where

t = typeof(MyClass); 
tArr = typeof(MyClass[]);
shake
  • 1,752
  • 4
  • 18
  • 22
0

The code is failing because some object in your array is not a primitive type, or is not something that implements the IConvertible interface You cannot use Convert.ChangeType() on such objects.

cdhowie
  • 158,093
  • 24
  • 286
  • 300
0

This is a solution that worked for me:

public static T[] CastArrayToType<T>(object[] collection)
{
    return Array.ConvertAll<object, T>(
        collection,
        delegate(object prop)
        {
            return (T)prop;
        }
    );
}
Bryun
  • 29
  • 3