Это довольно старый вопрос, но недавно я получил ту же проблему.И я не видел ответа, который мне подходит, поэтому поделюсь найденным решением.
- Почему массив int не может быть приведен или помещен в объект [] или строку []? Почему это не в штучной упаковке, я не знаю.Но это может быть упаковано явно, см. Решение ниже.
- Почему компилятор не улавливает это? Поскольку компилятор неправильно интерпретирует ситуацию: тип не является точно массивом объектов, поэтому он не знает, что с ним делать, и решает выполнить
.ToString()
для массива int, который возвращает один единственный параметр, содержащий имя типаа не сам список параметров.Он не делает этого со строковым массивом, потому что целевой тип уже является строкой - но с любым другим видом массива возникает такая же проблема (например, bool[]
).Рассмотрим var arr1 = new int[]{1,2};
с string.Format("{0}", arr1)
: если в строке формата указано только {0}
, вы получите только имя типа "System.Int32[]"
(без исключений).Если у вас есть больше заполнителей, например, string.Format("{0}{1}", arr1)
, то возникает исключение - потому что arr1
неверно истолкован как параметр one - а для компилятора, a 2 nd one отсутствует.Но я думаю, что концептуальная ошибка в том, что вы не можете конвертировать arr1
, то есть, если вы пытаетесь сделать (object[])arr1
- вы получаете: CS0030 Невозможно преобразовать тип 'int []' в'object []'
Решение:
Заполнение каждого элемента массива int не является решением, которое мне подходитпотому что в моем проекте я динамически создаю строку шаблона формата во время выполнения, содержащую {0}...{n}
- поэтому мне нужно передать массив в String.Format
.
Так что я нашел следующий обходной путь. Я создал универсальную вспомогательную функцию (которая, конечно, также может быть методом расширения, если вы предпочитаете):
// converts any array to object[] and avoids FormatException
object[] Convert<T>(T[] arr)
{
var obj = new List<object>();
foreach (var item in arr)
{
obj.Add((object)item);
}
return obj.ToArray();
}
Теперь, если вы попробуете это в примере ниже, который показывает исключение FormatException:
// FormatException: Index (zero based) must be greater than or equal to zero
// and less than the size of the argument list
var arr1 = (new int[] { 1, 2 });
string.Format("{0}{1}{0}{1}", arr1).Dump();
Исправление: Использование Convert(arr1)
в качестве 2 и параметр для string.Format(...)
, как показанониже:
// Workaround: This shows 1212, as expected
var arr1 = (new int[] { 1, 2 });
string.Format("{0}{1}{0}{1}", Convert(arr1)).Dump();
Попробуйте пример как DotNetFiddle
Вывод: Как кажетсясреда выполнения .NET действительно неправильно интерпретирует параметр, применяя к нему .ToString()
, если он еще не имеет тип object[]
.Метод Convert
не дает среде выполнения никакого другого выбора, кроме как сделать это правильно, потому что он возвращает ожидаемый тип.Я обнаружил, что явное преобразование типов не работает, поэтому необходима вспомогательная функция.
Примечание: Если вы вызываете метод много раз в цикле и вас беспокоит скорость,Вы также можете преобразовать все в строковый массив, который, вероятно, наиболее эффективен:
// converts any array to string[] and avoids FormatException
string[] ConvertStr<T>(T[] arr)
{
var strArr = new string[arr.Length];
for (int i = 0; i < arr.Length; i++)
{
strArr[i]=arr[i].ToString();
}
return strArr;
}
Это тоже работает.Для преобразования из другого типа данных, такого как словарь, вы можете просто использовать
string[] Convert<K,V>(Dictionary<K,V> coll)
{
return ConvertStr<V>(coll.Values.ToArray());
}
Обновление: С интерполяцией строк, другой короткий способ решить это:
var baz = string.Format("{0} and {1}", myInts.Select(s => $"{s}").ToArray());