冗余Object.ToString

时间:2013-12-12 11:20:15

标签: c# .net performance refactoring tostring

我正在审核以下代码。

private string MakeKey(int SnapshotID, string UserName, string BrandName)
{
    return string.Format("{0}:{1}:{2}", SnapshotID.ToString(), UserName, BrandName);
}

SnapshotID.ToString()冗余调用ToString()方法 可能发生的潜在问题是什么?例如速度。

修改
如果有人想改进,我添加了一个测试:http://pastebin.com/gynNjwT1

With ToString:      0.010884
Without ToString:   0.001446

With ToString:      0.005506
Without ToString:   0.002852

With ToString:      0.001155
Without ToString:   0.009117

With ToString:      0.003210
Without ToString:   0.001546

3 个答案:

答案 0 :(得分:3)

在此代码中...不,它只是多余的,甚至稍慢,因为String.Format()会再次调用ToString()本身的string

如果String.Format()IFormatProvider一起使用,则显式ToString()将覆盖它。

编辑(来自评论):关于效果的说明。与原始类型(ToString())拳击相比,它可能是或不慢(无用的 int调用)。我们应该衡量这一点,但很难说。什么慢? 虚拟函数调用装箱?与String.Format()总时间相比,这真的重要吗?它一直是already answered here on SO。 IMO如果它是作为智能优化完成的,它就没用了。

性能

OP为此做了一个小测试(见评论),只是为了有趣,在我的测试机器上得到了结果:

Test               Time [ms]
With ToString      0.002929
Without ToString:  0.003414

我重写测试不使用线程(因为它会添加更多变量,核心可能会有所不同,操作系统会动态加载它们)。有了这个(过于简单!)测试代码(来自OP测试):

Stopwatch sw = new Stopwatch();
sw.Start();
for (int x = 0; x < Count; x++)
{
    _temp = MakeKeyToString(1, "Ashley", "MyBrand");
}
sw.Stop();
TimeSpan test = TimeSpan.FromMilliseconds((double)sw.ElapsedMilliseconds);

我认为ToString()版本的速度更快(Count = 1000000)平均大约10/20纳秒。 IMO测量的东西如此之小,我们需要一个更好的测试环境和更专业的方法。更改String.Format()的代码以使用IFormatProvider

string MakeKeyToString(int SnapshotID, string UserName, string BrandName)
{
    return string.Format(CultureInfo.InvariantCulture,
        "{0}:{1}:{2}", SnapshotID.ToString(), UserName, BrandName);
}

再次更改所有内容:没有ToString()更快200纳秒。再次太小,不能以这种方式衡量。

结论

你甚至不能开始认为这是一种优化,会有太多因素会发生这种情况,它会很小,与总String.Format()时间相比会被忽视。更糟糕的是,如果你改变String.Format()使用IFormatProvider,它可能会引入微妙的错误,因为它会让你停下来思考“为什么会这样?应该有一个与文化相关的原因。也许.. “实际上......(可能)没有。

答案 1 :(得分:0)

在此示例中,通过调用Int32.ToString(),您可以避免将int装入Object的费用。

然而,调用.ToString(),然后调用String.Format调用.ToString()的开销可能会超过装箱的开销。就String.Format而言,所有这些都可以忽略不计。

答案 2 :(得分:-1)

不,代码是多余的并停止。此外SnapshotID不能为空,因为它是整数而不是可以为空的整数(int?)。在这种情况下,我认为ToString方法将被调用两次(一次显式调用,一次调用第一次调用的结果),因此可能会遇到一些性能差异。