考虑其参数为字符串的string.Format()
,以及重载列表中的object[]
或许多对象。
本声明成功:
string foo = string.Format("{0} {1}", 5, 6);
就像这样:
object[] myObjs = new object[] {8,9};
string baz = string.Format("{0} and {1}", myObjs;
字符串数组:
string[] myStrings = new string[] {"abc", "xyz"};
string baz = string.Format("{0} {1}", myStrings);
似乎单个指定的整数可以装箱或强制输入object
,而int[] myInts = new int[] {8,9};
string bar = string.Format("{0} and {1}", myInts);
则强制转换为字符串。
此声明在运行时时失败。
object[]
索引(从零开始)必须大于或等于零且小于参数列表的大小。
string[]
或{{1}}? 答案 0 :(得分:25)
呼叫失败的原因相同,以下内容也将失败:
string foo = string.Format("{0} {1}", 5);
您在format
中指定了两个参数,但只指定了一个对象。
编译器没有捕获它,因为int[]
作为对象传递,该对象是函数的完全有效参数。
另请注意,数组协方差不适用于值类型,因此您无法执行:
object[] myInts = new int[] {8,9};
但是你可以逃脱:
object[] myInts = new string[] { "8", "9" };
string bar = string.Format("{0} {1}", myInts);
这会有效,因为您将使用接受String.Format
的{{1}}重载。
答案 1 :(得分:3)
您的电话会被翻译成:
string foo = string.Format("{0} {1}", myInts.ToString());
导致此字符串:
string foo = "System.Int32[] {1}";
因为{1}没有参数,所以它会引发异常
答案 2 :(得分:2)
我认为您遇到问题的概念是int[]
未投放到object[]
的原因。这是一个示例,说明为什么会这么糟糕
int[] myInts = new int[]{8,9};
object[] myObjs = (object[])myInts;
myObjs[0] = new object();
问题是我们刚刚将一个对象添加到一个int数组中。
因此,您的代码中发生的事情是myInts
被强制转换为object
并且您没有第二个参数来填充{1}
答案 3 :(得分:1)
这是一个很老的问题,但我最近遇到了同样的问题。我还没有看到一个对我有用的答案,所以我会分享我找到的解决方案。
.ToString()
,它返回一个包含类型名称的单个参数,而不是参数列表本身。它不会对字符串数组执行此操作,因为目标类型已经是字符串 - 但是对于任何其他类型的数组,都会发生相同的问题(例如bool[]
)。 var arr1 = new int[]{1,2};
string.Format("{0}", arr1)
:只要格式字符串中只有{0}
,就只会返回类型名称"System.Int32[]"
(并且不会发生异常) )。 string.Format("{0}{1}", arr1)
,然后发生异常 - 因为arr1
被误解为一个参数 - 而对于编译器, a 2 nd one < / em>缺失。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 nd 参数作为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());
更新:使用字符串插值,另一种解决方法是:
res.pca <- prcomp(dataset, scale=TRUE)
fviz_eig(res.pca)
答案 4 :(得分:1)
使其工作的捷径(虽然不是最佳的):
int[] myInts = new int[] { 8, 9 };
string[] myStrings = Array.ConvertAll(myInts, x => x.ToString());
// or using LINQ
// string[] myStrings = myInts.Select(x => x.ToString()).ToArray();
bar = string.Format("{0} and {1}", myStrings);
答案 5 :(得分:0)
你的string.Format期待2个参数({0}和{1})。您只提供1个参数(int [])。你需要更像这样的东西:
string bar = string.Format("{0} and {1}", myInts[0], myInts[1]);
编译器没有注意到该问题,因为格式字符串是在运行时计算的。 IE编译器不知道{0}和{1}意味着应该有2个参数。
答案 6 :(得分:0)
这有效:
string bar = string.Format("{0} and {1}", myInts[0], myInts[1]);
编译器无法捕获它,因为它不会评估您的格式字符串。
你放弃顶部的例子与你在下面尝试做的事情不符...你提供了两个{}和两个参数,但在底部你只提供了一个参数。