我使用反射器查看String.Format方法的实现,并一直认为只有一个、两个和三个参数的String.Format重载是该方法的优化版本,它们比接受对象数组参数的版本更高效。然而,我发现内部实际上它们会创建一个对象数组,然后调用一个接受对象数组参数的方法。
1个参数:
public static string Format(string format, object arg0)
{
if (format == null)
{
throw new ArgumentNullException("format");
}
return Format(null, format, new object[] { arg0 });
}
2个参数
public static string Format(string format, object arg0, object arg1)
{
if (format == null)
{
throw new ArgumentNullException("format");
}
return Format(null, format, new object[] { arg0, arg1 });
}
3个参数
public static string Format(string format, object arg0, object arg1, object arg2)
{
if (format == null)
{
throw new ArgumentNullException("format");
}
return Format(null, format, new object[] { arg0, arg1, arg2 });
}
对象数组
public static string Format(string format, params object[] args)
{
if ((format == null) || (args == null))
{
throw new ArgumentNullException((format == null) ? "format" : "args");
}
return Format(null, format, args);
}
实际上它们最终都使用相同的代码,因此使用1、2和3个参数版本并不比使用对象数组版本更快。
所以我的问题是 - 为什么它们存在?
当您使用逗号分隔的值列表的对象数组版本时,编译器会自动将参数转换为对象数组,这是由于params/ParamArray关键字所致,这本质上就是1、2和3个版本所做的,因此它们似乎是冗余的。那么BCL设计者为什么要添加这些重载呢?
string.Format
只需要3个IL操作码,而如果不存在重载,则需要10个操作码。每个附加参数仅需要1个操作码,如果可以使用重载,则需要4个操作码。由于如果方法太多操作码就无法内联,因此这具有重大影响。 - Gabe