为什么String.Format的重载存在?

Gid*_*sey 17 .net string.format base-class-library

我使用Reflector来查看String.Format的实现,并且一直认为带有1,2和3参数的String.Format的重载是采用对象数组的方法的优化版本.但是,我发现内部它们创建了一个对象数组,然后调用一个带有对象数组的方法.

1 arg

public static string Format(string format, object arg0)
{
    if (format == null)
    {
        throw new ArgumentNullException("format");
    }
    return Format(null, format, new object[] { arg0 });
}
Run Code Online (Sandbox Code Playgroud)

2 args

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 });
}
Run Code Online (Sandbox Code Playgroud)

3 args

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 });
}
Run Code Online (Sandbox Code Playgroud)

对象数组

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);
}
Run Code Online (Sandbox Code Playgroud)

在内部,它们最终都使用相同的代码,因此使用1,2和3参数版本并不比对象阵列版本快.

所以我的问题是 - 它们为什么存在?

当您使用带有逗号分隔的值列表的对象数组版本时,编译器会自动将参数转换为对象数组,因为params/ParamArray关键字基本上是1,2和3版本所做的,因此它们似乎是多余的.为什么BCL设计师会增加这些重载?

Gab*_*abe 7

汉斯提到的一个原因是,在格式化字符串的大多数常见情况下,创建数组会带来很多不必要的开销.这节省了EXE中的空间.

另一个原因是并非所有语言都支持可变函数(params在C#中使用).这允许这些语言的用户避免为最常见的字符串格式化情况创建数组.对于没有简单的数组创建和初始化语法的语言,这可以节省很多.

  • @ChrisMarisic:创建数组的内存使用或GC开销不是问题所在; 这是额外的操作码.仅使用单个字符串替换调用`string.Format`只需要3个IL操作码,而如果不存在重载则需要10个操作码.如果可以使用过载,则每个附加参数仅需要1个操作码,如果使用数组则需要4个操作码.由于如果方法太多,则无法内联方法,这具有重要意义. (2认同)