5

我有以下 C# 代码:

string stg1 = "String 1";
string stg2 = "String 2";
string stg3 = "String 3";
string stg4;
stg4 = stg1 + stg3;
stg4 = stg4 + stg2 + stg3;
stg4 = "";
stg3 = "";

创建了多少个字符串对象?
我认为创建了 7 个字符串对象:"String 1", "String 2", "String 3", stg1 + stg3, stg4 + stg2 + stg3, "", 和"". 我不确定第 4 条语句 ( string stg4;) 是否创建了一个字符串对象,并且我在某处读到将空字符串分配给一个字符串""并不会创建一个对象,但我认为这不是真的。你们有什么感想?

4

2 回答 2

11

我在某处读到,将空字符串“”分配给字符串不会创建对象,但我认为这不是真的。你们有什么感想?

这并不完全正确。肯定会为空字符串创建一个字符串实例。

话虽如此,该代码中不会有两个实例;只有一个。除非您在编译时禁用该设置,否则编译器将查找所有相同的编译时文字字符串,并仅创建一个string对象来表示它,并为定义该字符串的所有变量提供对该字符串的相同引用。这被称为“实习”。

请注意,默认情况下,字符串实习仅适用于编译时文字字符串,而不是运行时生成的字符串。如果在运行时生成两个相等的字符串,它们不一定是对同一个字符串对象的引用。

除此之外,您的分析是正确的。

同样值得注意的是,虽然您正确地说明这stg4 + stg2 + stg3将导致仅创建一个字符串,但您并没有真正解释原因,而且为什么会这样也不清楚。

最初的猜测可能是这里将执行两个操作,首先stg4 + stg2是 ,这将产生一个字符串,然后将该结果连接起来stg3以创建最终结果。但事实并非如此。编译器实际上会生成一个对 的调用string.Concat将所有三个字符串作为参数传递(Concat定义为Concat(params string[] args)它可以接受任意数量的字符串),并且Concat足够聪明,可以只创建一个字符串,而不是为 n-1 中间体创建字符串价值观。

于 2013-02-23T00:10:11.770 回答
6

Servy 的回答非常准确。我特别喜欢对串联的正确分析。

我只想在这个出色的答案中添加一点额外的点,那就是它是实现定义的,非文字String.Empty是否与文字一起实习""。.NET 的某些版本会自动执行,而某些版本不会自动执行。

http://ericlippert.com/2009/09/28/string-interning-and-string-empty/

更多细节。

于 2013-02-23T00:47:59.370 回答