Преобразуйте массив 'enum' в массив 'int'
Я пытаюсь преобразовать массив Enum в массив int:
public enum TestEnum
{
Item1,
Item2
}
int[] result = Array.ConvertAll<TestEnum, int>(enumArray, new Converter<TestEnum, int>(Convert.ToInt32));
По какой-то причине Convert.ToInt32 не работает при использовании в Array.ConvertAll, поэтому мне пришлось внести некоторые изменения:
int[] result = Array.ConvertAll<TestEnum, int>(enumArray, new Converter<TestEnum, int>(ConvertTestEnumToInt));
public static int ConvertTestEnumToInt(TestEnum te)
{
return (int)te;
}
Просто из любопытства, есть ли способ работать без дополнительного метода?
Привет
Ответы
Ответ 1
Просто с помощью анонимного метода:
int[] result = Array.ConvertAll<TestEnum, int>(
enumArray, delegate(TestEnum value) {return (int) value;});
или с С# 3.0, lambda:
int[] result = Array.ConvertAll(enumArray, value => (int) value);
Ответ 2
К счастью для нас, С# 3.0 включает в себя операцию Cast
:
int[] result = enumArray.Cast<int>().ToArray();
Если вы перестанете использовать массивы и начнете использовать IEnumerable<>
, вы даже можете избавиться от вызова ToArray()
.
Ответ 3
TestEnumArray.Select(x = > (int) x)). ToArray()
Ответ 4
int [] b = Array.ConvertAll((int []) Enum.GetValues (typeof (testEnum)), Convert.ToInt32);
Ответ 5
FYI: проверено на .Net4ClientProfile и VS2010
На самом деле вам даже не нужно использовать LINQ. Вы можете просто бросить его обычным способом, при условии, что вы отбрасываете тип до object
.
Наличие:
enum One { one0, one1, one2, one3 };
enum Two { two0, two1, two2, two3 };
One[] vals = new One[] { One.one0, One.one3 };
мы можем играть:
//Two[] aa = (Two[])vals; // impossible
Two[] aa = (Two[])(object)vals; // possible!
Two bb = aa[1]; // == Two.two3
Сначала я был действительно удивлен, что вторая строка не бросает InvalidCast. Но это не так.
Глядя на типы, объясняет вещи немного:
bool check2 = bb.GetType().FullName == "Two"; // well, you'd guess that
bool check3 = aa.GetType().FullName == "One[]"; // what?!
Серьезно! Массив aa
не Two[]
. Тип массива был "потерян переменной", когда он был добавлен к object
, но оба vals
и (object)vals
, конечно же, относятся к одному и тому же объекту. Затем, после следующего приведения, он все еще является объектом aa
, исходным массивом One[]
, просто скрытым за новым типом переменной.
Объект/переменная bb
имеет тип Two
, потому что элемент массива считывается как элемент массива Two[]
(наряду с типами переменных). Реальный массив One [] скрывается типом Two[]
, поэтому индексирование Two[]
должно приводить к типу Two
.
Кроме того, поскольку фактический тип скрыт, и поскольку типы Enum кажутся легко обработанными, давайте еще раз проверить:
var numbers = (int[])(object)vals;
var cc = numbers[0] + 10; // == 10, from one0 value
var dd = numbers[1] + 10; // == 13, from one3 value
и аналогичным образом:
bool check4 = numbers.GetType().FullName == "One[]"; // not System.Int32[]
Итак, как вы уже могли догадаться, возможен и другой способ:
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)
а int [] также запоминает свой реальный тип, даже если его отличить от One[]
:
bool check5 = numbers2.GetType().FullName == "System.Int32[]";
Кроме того, вы не можете доверять операторам as
и is
, когда массив передается как object
:
bool really_true1 = vals is One[];
bool really_true2 = vals is Two[];
bool really_true3 = vals is System.LoaderOptimization[];
Это был "гота!". для меня недавно.
На самом деле повторно использует исходный объект массива (вместо дублирования его как с LINQ), и он предоставляет его как другой тип - будь то Two [] или int []. Кажется, это "настоящий бросок", без бокса. Многое отличается от копирования и преобразования с помощью LINQ.