冗余对象.ToString

本文关键字:ToString 对象 冗余 | 更新日期: 2024-09-20 07:18:56

我正在查看以下代码。

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

冗余对象.ToString

在这个代码中。。。不,它只是多余的,甚至稍微慢一点,因为String.Format()将在string本身上再次调用ToString()

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

编辑(来自注释):关于性能的注释。与基元类型(int)装箱相比,它可能慢也可能慢(无用的ToString()调用)。我们应该衡量一下,但很难说。什么更慢?虚拟函数调用还是装箱?与String.Format()的总时间相比,这真的重要吗?这里已经在SO上回答了这个问题。IMO如果它是作为智能优化完成的,那就没有用了。

性能

OP对此进行了一个小测试(见评论),只是为了的乐趣,在我的测试机上的结果:

测试时间[ms]带ToString 0.002929不带ToString:0003414

我重写了测试,不使用线程(因为它会添加更多的变量,内核可能会不同,操作系统会动态加载它们)。有了这个(过于简单!)测试代码(源自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,它可能会引入微妙的错误,因为它会让你停下来思考"为什么这样?应该有一个与文化相关的原因。也许…"而实际上。。。(可能)没有。

在本例中,通过调用Int32.ToString(),可以避免将int装箱为Object的开销。

然而,调用.ToString(),然后让String.Format调用.ToString()的开销可能超过装箱的开销。并且所有这些对于CCD_ 26来说都是可忽略的。

没有,代码是多余的并且停止了。此外,SnapshotID不能为null,因为它是一个整数而不是可为null的整数(int?)。在这种情况下,ToString方法将被调用两次(一次是显式调用,一次是在第一次调用的结果上调用),因此可能会面临一些性能差异。