[ACCEPTED]-How to convert object[] to a more specifically typed array-casting

Accepted answer
Score: 33

It's not really a cast as such (I'm allocating 4 a new array and copying the original), but 3 maybe this can help you out?

Type myType = typeof(string);
object[] myArray = new object[] { "foo", "bar" };

Array destinationArray = Array.CreateInstance(myType, myArray.Length);
Array.Copy(myArray, destinationArray, myArray.Length);

In this code, destinationArray will 2 be an instance of string[] (or an array of whatever 1 type myType was).

Score: 2

You can't perform such a cast, because the 6 arrays object[] and string[] are actually 5 different types and are not convertible. However, if 4 you wanted to pass different such types 3 to a function, just make the parameter IEnumerable. You 2 can then pass an array of any type, list 1 of any type, etc.

    // Make an array from any IEnumerable (array, list, etc.)
    Array MakeArray(IEnumerable parm, Type t)
    {
        if (parm == null)
            return Array.CreateInstance(t, 0);
        int arrCount;
        if (parm is IList)     // Most arrays etc. implement IList
            arrCount = ((IList)parm).Count;
        else
        {
            arrCount = 0;
            foreach (object nextMember in parm)
            {
                if (nextMember.GetType() == t)
                    ++arrCount;
            }
        }
        Array retval = Array.CreateInstance(t, arrCount);
        int ix = 0;
        foreach (object nextMember in parm)
        {
            if (nextMember.GetType() == t)
                retval.SetValue(nextMember, ix);
            ++ix;
        }
        return retval;
    }
Score: 2

This is not a one liner but it can be done 9 with two lines. Given your specified Array of 8 elements of the correct type myArray and the specified 7 Type parameter myType, dynamically calling .Cast<"myType">.ToArray() would 6 work.

var typeConvertedEnumerable = typeof(System.Linq.Enumerable)
    .GetMethod("Cast", BindingFlags.Static | BindingFlags.Public)
    .MakeGenericMethod(new Type[] { myType })
    .Invoke(null, new object[] { myArray });
var typeConvertedArray = typeof(System.Linq.Enumerable)
    .GetMethod("ToArray", BindingFlags.Static | BindingFlags.Public)
    .MakeGenericMethod(new Type[] { myType })
    .Invoke(null, new object[] { typeConvertedEnumerable });

While the method generation is slower 5 than a direct call, it is O(1) on the size 4 of the array. The benefit of this approach 3 is, if IEnumerable<"myType"> would be acceptable, the second 2 line is not needed, and therefore I do not 1 believe the array will be copied.

Score: 1

You'd have to manually go through every 4 object, get the most generic common type 3 between them, and then create a new array 2 of that type and copy the elements. There's 1 no one-liner for this.

Score: 1

This will create the array that you want, but 4 I don't know what you're going to do with 3 it afterwards, since the compiler still 2 doesn't know what the type of the array 1 object is.

Type myType = typeof(string);
object[] myArray = new object[] { "foo", "bar" };

Array myArrayOfTheCorrectType = Array.CreateInstance(myType, myArray.Length);
for (int index = 0; index < myArray.Length; index++)
    myArrayOfTheCorrectType.SetValue(myArray[index], index);
Score: 1

I would say the answer is it cant be cast. I 8 know alot of other people have offered solutions, but 7 the answer is no. I think the reason is 6 because the type of the array is object, which 5 is lower than string. The compiler will 4 not let the upconversion happen unless you 3 do it manually. I also played around with 2 the DLR stuff, but it still types it as 1 object.

class Program
{
    static void Main(string[] args)
    {
        // could actually be anything else
        Type myType = typeof(string);
        Type myArrayType = Array.CreateInstance(myType, 1).GetType();

        // i already know all the elements are the correct types
        object[] myArray = new object[] { "foo", "bar" };

        MethodInfo castMethod = typeof(Enumerable).GetMethod("Cast").MakeGenericMethod(myArrayType);
        object castedObject = castMethod.Invoke(null, new object[] { myArray });
    }

    public static T Cast<T>(object o)
    {
        return (T)o;
    }
}

More Related questions