【问题标题】:Why do the overloads of String.Format exist?为什么存在 String.Format 的重载?
【发布时间】:2010-05-09 05:35:51
【问题描述】:

我使用 Reflector 来查看 String.Format 的实现,并且一直认为采用 1、2 和 3 个参数的 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 设计者要添加这些重载?

【问题讨论】:

    标签: .net string.format base-class-library


    【解决方案1】:

    正如 Hans 所提到的,其中一个原因是,在格式化字符串的最常见情况下,创建数组会产生很多不必要的开销。这样可以节省 EXE 中的空间。

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

    【讨论】:

    • “创建一个数组是很多不必要的开销” 数组是在方法内部创建的,在“开销”方面有什么不同?
    • @ChrisMarisic:问题不在于创建数组的内存使用或 GC 开销;这是额外的操作码。仅用一个字符串替换调用string.Format 只需要 3 个 IL 操作码,而如果不存在重载则需要 10 个操作码。如果可以使用重载,每个附加参数只需要 1 个操作码,而如果它使用数组则需要 4 个操作码。由于如果操作码过多,则无法内联方法,因此这会产生重大影响。
    • 所以重载是为了增加 Format 调用本身在使用它的地方内联的可能性?如果必须使用 params 重载,它永远不会被内联吗?
    • 重载增加了包含 Format 调用的方法被内联的可能性。
    【解决方案2】:

    您忘记了拨打电话所需的应用程序中的代码。创建数组并填充它比仅传递 3 个参数需要更多的 IL。

    【讨论】:

    • 你说得对。我没有考虑过。我想你可以说这些方法优化了调用代码的大小,而不是我一直认为它们存在的性能。
    • 所以如果你在直接 IL 中调用重载有意义吗?
    猜你喜欢
    • 2011-09-12
    • 2013-05-23
    • 2011-06-07
    • 1970-01-01
    • 1970-01-01
    • 2017-10-31
    • 2018-07-14
    • 1970-01-01
    相关资源
    最近更新 更多