Как преобразовать объект [] в более типизированный массив
Это было бы довольно просто, если бы я знал типы во время компиляции или если это был общий параметр, потому что я мог бы сделать что-то вроде myArray.Cast<T>()
Но то, что у меня на самом деле, по существу это. У меня нет известного типа или общего параметра. У меня есть переменная System.Type
.
// could actually be anything else
Type myType = typeof(string);
// i already know all the elements are the correct types
object[] myArray = new object[] { "foo", "bar" };
Есть ли какая-то магия отражения, которую я могу сделать, чтобы получить ссылку string[]
, содержащую те же данные? (где string
не известно во время компиляции)
Ответы
Ответ 1
На самом деле это не актерский состав (я выделяю новый массив и копирую оригинал), но, может быть, это может помочь вам?
Type myType = typeof(string);
object[] myArray = new object[] { "foo", "bar" };
Array destinationArray = Array.CreateInstance(myType, myArray.Length);
Array.Copy(myArray, destinationArray, myArray.Length);
В этом коде destinationArray
будет экземпляр string[]
(или массив любого типа myType
).
Ответ 2
Вы не можете выполнить такой отбор, потому что объект массивов [] и строка [] на самом деле являются разными типами и не являются конвертируемыми. Однако, если вы хотите передать разные типы в функцию, просто введите параметр IEnumerable. Затем вы можете передать массив любого типа, список любого типа и т.д.
// 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;
}
Ответ 3
Вам придется вручную пройти через каждый объект, получить общий общий тип между ними, а затем создать новый массив этого типа и скопировать элементы. Для этого нет ни одного лайнера.
Ответ 4
Это создаст массив, который вы хотите, но я не знаю, что вы собираетесь с ним делать после этого, поскольку компилятор все еще не знает, что такое тип объекта массива.
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);
Ответ 5
Я бы сказал, что ответ не может быть брошен. Я знаю, что многие люди предлагали решения, но ответ - нет. Я думаю, причина в том, что тип массива - это объект, который меньше, чем строка. Компилятор не допустит, чтобы upconversion произошла, если вы не сделаете это вручную. Я также играл с материалом DLR, но он все еще набирает его как объект.
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(Program).GetMethod("Cast").MakeGenericMethod(myArrayType);
object castedObject = castMethod.Invoke(null, new object[] { myArray });
}
public static T Cast<T>(object o)
{
return (T)o;
}
}