Как преобразовать объект в объект []

У меня есть object, значение которого может быть одним из нескольких типов массивов, таких как int[] или string[], и я хочу преобразовать его в string[]. Моя первая попытка не удалась:

void Do(object value)
{
    if (value.GetType().IsArray)
    {
        object[] array = (object[])value;
        string[] strings = Array.ConvertAll(array, item => item.ToString());
        // ...
    }
}

с ошибкой времени выполнения Unable to cast object of type 'System.Int32[]' to type 'System.Object[]', что имеет смысл в ретроспективе, поскольку мой int[] не содержит целых чисел в блоке.

После того, как я выскочил, я пришел к этой рабочей версии:

void Do(object value)
{
    if (value.GetType().IsArray)
    {
        object[] array = ((Array)value).Cast<object>().ToArray();
        string[] strings = Array.ConvertAll(array, item => item.ToString());
        // ...
    }
}

Я думаю, что все в порядке, но кажется довольно запутанным. У кого-то есть более простой способ?

Ответ 1

Вам не нужно преобразовывать его в массив, а затем использовать LINQ. Вы можете сделать это более потоковым способом, только преобразовывая в массив в конце:

var strings = ((IEnumerable) value).Cast<object>()
                                   .Select(x => x == null ? x : x.ToString())
                                   .ToArray();

(Обратите внимание, что это сохранит нули, а не бросает исключение. Оно также отлично подходит для любого IEnumerable, а не только для массивов.)

Ответ 2

.ToArray делает несколько распределений памяти в большинстве случаев, но есть несколько способов обойти это:

object value = new[] { 1, 2.3 };

IList list = value as IList;
string[] strings = new string[list.Count];

for (int i = 0; i < strings.Length; i++)
    strings[i] = Convert.ToString(list[i]);

В большинстве случаев это может быть чересчур избыточным и пустой тратой вертикального пространства, поэтому я бы использовал что-то вроде принятого ответа с необязательным нулевым условным оператором ?, чтобы проверить, является ли источник массивом:

string[] strings = (value as Array)?.Cast<object>().Select(Convert.ToString).ToArray();

Ответ 3

void Do(object value)
{
    if (value.GetType().IsArray)
    {
       string[] strings = ((object[]) value).Select(obj => Convert.ToString(obj)).ToArray();
    }
}