FYI: tested on .Net4ClientProfile and VS2010
Actually, you don't even need to use LINQ. You can just cast it in a normal way, provided that you drop the type down to object.
Having:
enum One { one0, one1, one2, one3 };
enum Two { two0, two1, two2, two3 };
One[] vals = new One[] { One.one0, One.one3 };
we can play:
//Two[] aa = (Two[])vals; // impossible
Two[] aa = (Two[])(object)vals; // possible!
Two bb = aa[1]; // == Two.two3
At first, I was really suprised that the second line doesn't throw InvalidCast. But it does not.
Looking at the types explains things a little:
bool check2 = bb.GetType().FullName == "Two"; // well, you'd guess that
bool check3 = aa.GetType().FullName == "One[]"; // what?!
Seriously! The aa array is not Two[]. The array type has been "lost by variable" when it was cast to object, but both vals and (object)vals of course still refer to the same object. Then, after the following cast, it's still the aa object, the original array of One[], just hidden behind a new variable type.
The bb object/variable has type of Two because the array's item read as an item of a Two[] array (along with the variable's types). The real array One[] is concealed by the Two[] type, so indexing the Two[] must result in value of Two type.
Furthermore, since the actual type is hidden and since Enum types seem to be treated lightly, let's check another thing:
var numbers = (int[])(object)vals;
var cc = numbers[0] + 10; // == 10, from one0's value
var dd = numbers[1] + 10; // == 13, from one3's value
and similarly:
bool check4 = numbers.GetType().FullName == "One[]"; // not System.Int32[]
So, as you might already guess, the other way around is possible too:
var numbers2 = new int[]{ 0, 2, 99 };
var enums = (One[])(object)numbers2;
One ee = enums[0]; // == One.one0
One ff = enums[1]; // == One.one2
One gg = enums[2]; // == ((One)99)
and int[] also remembers its real type, even if casted to One[]:
bool check5 = numbers2.GetType().FullName == "System.Int32[]";
Even further, you cannot trust the as and is operators when the array is passed as object:
bool really_true1 = vals is One[];
bool really_true2 = vals is Two[];
bool really_true3 = vals is System.LoaderOptimization[];
This one was a 'gotha!' for me recently.
It actually reuses the original array object (instead of duplicating it like with LINQ) and it exposes it as different type - be it Two[] or int[]. It's seems to be a "true cast", no boxing. Much different than LINQ-driven copying&conversion.
int[] result = Array.ConvertAll<TestEnum, int>(enumArray, new Converter<TestEnum, int>(Convert.ToInt32));is really the same asint[] result = Array.ConvertAll(enumArray, Convert.ToInt32);. The overload of theToInt32method in question takes in anobjectparameter. The delegate type (a constructed generic typeConverter<TestEnum, int>) takes in aTestEnum. Now sinceTestEnumderives fromobject, you are surprised everything doesn't work. But this kind of magic (came in C# 2) is only allowed with reference types, andTestEnumis a value type.int[] result = Array.ConvertAll(enumArray, x => Convert.ToInt32(x));. In that case the lambda contains an invisible boxing fromTestEnumtoobject. But as I said, Gravell's solution is more elegant and fast.