Change the innermost element type of a jagged array — any .NET language: C#, F#, VB.NET, MSIL, C++/CLI, etc
C# - 396 440 595

I'm not entirely sure why I did this, and I can't help but feel I'm missing something. Rewrote the old c (for copy) method as a for-loop in the ChangeElementType method (f). Unless I find something substantial, I think I'll not be making this any shorter.

Golfed code:

using A=System.Array;using T=System.Type;class P{T g(T o){return o.IsArray?g(o.GetElementType()).MakeArrayType(o.GetArrayRank()):typeof(long);}A f(A a){var R=a;int i,r;for(var x=new int[i=r=a.Rank];;){if(i&lt;1){if(a!=R)return R;R=A.CreateInstance(g(a.GetType().GetElementType()),x);i=1;}if(--i&lt;r)if(x[i]--&gt;0)i+=2;else x[i]=a.GetLength(i);else{var o=a.GetValue(x);R.SetValue(o is A?f((A)o):o,x);}}}}


Readable code with an excuse for a test:

using A=System.Array;
using T=System.Type;

class P
{
    // turns a type like "int[,][]" into "long[,][]"
    T g(T o)
    {
        return o.IsArray?g(o.GetElementType()).MakeArrayType(o.GetArrayRank()):typeof(long);
    }

    // ChangeElementType
    A f(A a)
    {
        var R=a; // R is the result, a gives us the type and a nice default value
        int i,r; // i is a counter, r is the rank

        // this loop first counts backwards filling the x array with the dimension lengths
        // then it does a tree traversal and copies things about
        for(var x=new int[i=r=a.Rank];;) // create the x array, and sets i and r
        {
            if(i&lt;1)
            { // gone off start
                if(a!=R) // been here before
                    return R; // return the result
                R=A.CreateInstance(g(a.GetType().GetElementType()),x); // create the array to fill
                i=1; // move to start of x
            }

            if(--i&lt;r) // move back
                if(x[i]--&gt;0) // decrement index
                    i+=2; // move forward instead
                else 
                    x[i]=a.GetLength(i); // reset index
            else
            {
                var o=a.GetValue(x); // get the int/array
                R.SetValue(o is A?f((A)o):o,x); // if it's an array, Change it, if not, pass it directly (the int)
            }
        }
    }

    // test method (prints True if the code works, might print False if it doesn't)    
    static void Main()
    {
        string old = "";

        var a = new int[10][,];

        for (int i = 0; i &lt; 10; i++)
        {
            a[i] = new int[3,5];

            for (int j = 0; j &lt; 3; j++)
            {
                for (int k = 0; k &lt; 5; k++)
                {
                    int v = i * j * k;
                    a[i][j,k] = v;
                    old += v.ToString();
                }
            }
        }

        long[][,] l = (long[][,])(new P().f(a));

        string nwe = "";

        for (int i = 0; i &lt; 10; i++)
        {
            for (int j = 0; j &lt; 3; j++)
            {
                for (int k = 0; k &lt; 5; k++)
                {
                    nwe += l[i][j,k].ToString();
                }
            }
        }

        System.Console.WriteLine(old == nwe);

        System.Console.ReadKey(true);
    }
}