C#的toString()性能问题

8

我对C#中的ToString()方法很好奇。以以下代码为例:

object height = 10;

string heightStr = height.ToString();

当我在 height 上调用 ToString() 方法时,我会得到一个字符串类型的返回值。这个字符串是否由运行时分配内存?

3
ToString()是为了人类而设计的,性能不是问题,因为人们无法读得那么快。但应该无论如何保留ToString()。 - Hans Passant
2个回答

8

是的,运行时会为您创建或请求的任何字符串对象分配内存,包括从方法调用返回的对象。

但是,这绝对不是您需要担心的事情。它不会对应用程序的性能产生任何明显影响,您不应该陷入过早优化代码的诱惑。

Int32.ToString方法非常快。它调用在CLR级别编写的本机代码,这不太可能成为任何应用程序的性能瓶颈。


实际上,这里的真正性能问题将是装箱,即将值类型转换为类型object,然后再转换回来的过程。这是因为您将height变量声明为object类型,然后将整数值赋给它。

更好的做法是将height明确声明为int类型,如下所示:

int height = 10;
string heightStr = height.ToString();

一组装箱/拆箱操作并不比分配字符串更低效。 - Matti Virkkunen
@Matti:不,一个集合可能不是。我需要看到性能数据才能确定,但这在这里并不重要。我试图做出的区别是装箱通常是值得避免的事情。在编写.NET代码时,它被认为是一种“不良实践”,对于每个人来说都应该意识到这一点。字符串分配不是问题,也不是需要避免的东西。在应用程序中,重复的装箱/拆箱操作可能会导致性能问题的潜力更大。 - Cody Gray
1
作为一个小提示:如果您在值类型变量/表达式上调用虚拟方法(例如ToString()),而该值类型变量/表达式没有显式覆盖它,那么也会发生装箱。对于int,确实有一个明确的int.ToString(),但并不总是如此。 - Marc Gravell
针对“您创建或请求的任何字符串对象”,当然还涉及到内部化的问题-虽然不适用于此处,但“任何”是一个很大的声明。 - Marc Gravell
1
我必须不同意开头的陈述。在某些情况下,这可能会成为性能问题。如果这种情况在紧密循环中多次发生,分配的累积效应可能会导致昂贵的垃圾回收。在游戏中,垃圾回收非常明显。在像紧凑框架中的单一代收集器中,您还面临着碎片化的风险,从而为收集器带来更多工作。 - paulecoyote
任何应用程序都是一个广泛的范畴,而且也不是所有基于持续快速速度的应用程序都需要分配内存。例如实时媒体和VoIP应用程序。 - Fabian Kamp

4

是的。 在这种情况下,创建一个类的新实例(如字符串类)将为实例分配内存。


1
我不太确定字符串是不可变的这一事实在这里的相关性。他没有修改现有的“String”类实例,而是将“ToString”函数的结果赋值给一个类型为“string”的变量。即使它不是不可变的,这也将创建该类的新实例。 - Cody Gray
@Cody,我提到这点是为了强调所有字符串实例都被分配了新的内存地址这一事实。你是对的,它并不是非常相关,但我认为它可能会带来更多的清晰度。无论如何,我已经删除了不可变性的提及以避免混淆。 - Kyle Trauberman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接