У меня есть сторонняя библиотека, возвращающая массив объектов массивов объектов, которые я могу вставить в объект []:
object[] arr = myLib.GetData(...);
Результирующий массив состоит из объектов [] записей, поэтому вы можете думать о возвращаемом значении как о некотором наборе записей с внешним массивом, представляющим строки и внутренние массивы, содержащие значения полей, где некоторые поля могут не заполняться (a зубчатый массив). Чтобы получить доступ к отдельным полям, мне нужно выполнить следующие действия:
int i = (int) ((object[])arr[row])[col];//access a field containing an int
Теперь, когда я ленив, я хочу получить доступ к следующим элементам:
int i = (int) arr[row][col];
Для этого я использую следующий запрос Linq:
object[] result = myLib.GetData(...);
object[][] arr = result.Select(o => (object[])o ).ToArray();
Я пробовал использовать простой листинг, например object[][] arr = (object[][])result;
, но это не выполняется с ошибкой времени выполнения.
Теперь, мои вопросы:
- Есть ли более простой способ сделать это? У меня такое ощущение, что некоторые Отличный актер должен сделать трюк?
- Также меня беспокоит производительность так как я должен переделать много данных, чтобы спасти меня от кастинга, поэтому я интересно, действительно ли это стоит?
EDIT:
Спасибо всем за быстрые ответы.
@James: Мне нравится, что ваш ответ завершает виновника в новом классе, но недостатком является то, что мне всегда приходится делать упаковку Linq при взятии в исходном массиве, а индексатору нужны значения строк и столбцов int i = (int) arr[row, col];
(мне нужно чтобы получить полный ряд, а также object[] row = arr[row];
, извините, не опубликовал это в начале).
@Sergiu Mindras: Как и Джеймс, я чувствую, что метод расширения немного опасен, поскольку он применим ко всем переменным object[]
.
@Nair: я выбрал свой ответ для моей реализации, так как ему не нужно использовать оболочку Linq, и я могу получить доступ к обоим отдельным полям с помощью int i = (int) arr[row][col];
или всей строки с помощью object[] row = arr[row];
@quetzalcoatl и @Abe Heidebrecht: Спасибо за подсказки на Cast<>()
.
Заключение: Я бы хотел выбрать ответ Джеймса и Найра, но, как я уже сказал выше, решение Nair дает мне (я думаю) лучшую гибкость и производительность. Я добавил функцию, которая будет "сглаживать" внутренний массив, используя вышеуказанный оператор Linq, потому что у меня есть другие функции, которые нужно подавать с такой структурой.
Вот как я (грубо) реализовал его (взято из решения Найра:
открытый класс CustomArray { данные частного объекта []; public CustomArray (объект [] arr) { data = arr; }
//get a row of the data
public object[] this[int index]
{ get { return (object[]) data[index]; } }
//get a field from the data
public object this[int row, int col]
{ get { return ((object[])data[row])[col]; } }
//get the array as 'real' 2D - Array
public object[][] Data2D()
{//this could be cached in case it is accessed more than once
return data.Select(o => (object[])o ).ToArray()
}
static void Main()
{
var ca = new CustomArray(new object[] {
new object[] {1,2,3,4,5 },
new object[] {1,2,3,4 },
new object[] {1,2 } });
var row = ca[1]; //gets a full row
int i = (int) ca[2,1]; //gets a field
int j = (int) ca[2][1]; //gets me the same field
object[][] arr = ca.Data2D(); //gets the complete array as 2D-array
}
}
Итак - еще раз - спасибо всем! Это всегда настоящее удовольствие и просвещение, чтобы использовать этот сайт.