6

在 C# 中,如果我们想创建一个类型的变量,string我们可以使用:

string str="samplestring"; // this will allocate the space to hold the string

在C#中,string是类类型,所以如果我们要创建一个对象,通常我们必须使用new关键字。那么如果没有newor ,分配是如何发生的constructors呢?

4

7 回答 7

8

当你写

string str="samplestring";

编译器会生成两条指令:

  1. 首先,ldstr从元数据中获取字符串文字;分配必要的内存量;创建一个新String对象并将对它的引用压入堆栈。
  2. 然后stloc(或其中一种简短形式,例如stloc.0)将该引用存储在局部变量str中。

请注意,这ldstr将为每个字符序列分配一次内存。

因此,在下面的示例中,两个变量都将指向内存中的同一个对象:

// CLR will allocate memory and create a new String object
// from the string literal stored in the metadata
string a = "abc";

// CLR won't create a new String object. Instead, it will look up for an existing
// reference pointing to the String object created from "abc" literal
string b = "abc";

这个过程称为字符串实习

此外,如您所知,在 .NET 中字符串是不可变的。所以对象的内容String在对象创建之后就不能再改变了。也就是说,每次连接字符串时,CLR 都会创建一个新String对象。

例如,以下代码行:

string a = "abc";
string b = a + "xyz";

将被编译成以下 IL(当然不完全是):

  1. ldstr将分配内存并从字面量创建一个新String对象"abc"
  2. stloc将对该对象的引用存储在局部变量中a
  3. ldloc将该引用推入堆栈
  4. ldstr将分配内存并从字面量创建一个新String对象"xyz"
  5. call将调用堆栈System.String::Concat上的这些对象String
  6. 一个调用System.String::Concat会分解成几十条IL指令和内部调用。简而言之,它将检查两个字符串的长度并分配必要的内存量来存储连接结果,然后将这些字符串复制到新分配的内存中。
  7. stloc将对新创建的字符串的引用存储在局部变量中b
于 2012-10-19T15:44:13.777 回答
6

这只是 C# 编译器通过允许字符串文字为您提供快捷方式。

如果您愿意,您可以通过任意数量的不同构造函数来实例化一个字符串。例如:

 char[] chars = { 'w', 'o', 'r', 'd' };
 string myStr = new String(chars);
于 2012-10-19T14:35:26.273 回答
3

根据 MS 文档,您不需要使用 new 命令来使用默认字符串构造函数。

然而,这确实有效。

char[] letters = { 'A', 'B', 'C' };
string alphabet = new string(letters);

c# 字符串(来自 MSDN 编程指南)

于 2012-10-19T14:34:40.933 回答
2

字符串实际上是引用类型。该变量保存对内存中值的引用。因此,您只是将引用而不是值分配给对象。我建议你看一下 Pluralsight 的这个视频(你可以获得 14 天的免费试用期)

Pluralsight C# 基础 - 字符串

免责声明:我与 Pluralsight 没有任何关系。我是订阅者,我喜欢那里的视频

于 2012-10-19T14:40:36.097 回答
1

尽管 .net 中的一切都是对象,但仍有一些不需要实例化的原始类型(int、bool 等)。正如你在这里看到的,一个字符串是一个 4 字节的地址引用,指向一个可以扩展到 2GB 的向量/数组结构。请记住字符串是不可变类型,因此当您更改字符串时,您不会编辑现有变量,而是为文字值分配新内存,然后更改字符串指针以指向新的内存结构。希望有帮助

于 2012-10-19T14:33:04.590 回答
0

当您在内部使用文字创建字符串时,取决于您的程序集是否标有 NoStringInterning 标志,它看起来像:

String str = new String("samplestring");
// or with NoStringInterning
String str = String.Intern("samplestring");
于 2012-10-19T15:00:56.797 回答
-4

在java中,如果你写这样的东西:

String s1 = "abc";
String s2 = "abc";

内存将在所谓的字符串池中为“abc”分配,s1 和 s2 都将引用该内存。并且 s1 == s2 将返回 true (“==”比较引用)。但是如果你写:

String s1 = new String("abc");
String s1 = new String("abc");

s1 == s2 将返回 false。我猜在c#中它会是一样的。

于 2012-10-19T14:38:48.267 回答