在 C# 中,如果我们想创建一个类型的变量,string
我们可以使用:
string str="samplestring"; // this will allocate the space to hold the string
在C#中,string
是类类型,所以如果我们要创建一个对象,通常我们必须使用new
关键字。那么如果没有new
or ,分配是如何发生的constructors
呢?
在 C# 中,如果我们想创建一个类型的变量,string
我们可以使用:
string str="samplestring"; // this will allocate the space to hold the string
在C#中,string
是类类型,所以如果我们要创建一个对象,通常我们必须使用new
关键字。那么如果没有new
or ,分配是如何发生的constructors
呢?
当你写
string str="samplestring";
编译器会生成两条指令:
ldstr
从元数据中获取字符串文字;分配必要的内存量;创建一个新String
对象并将对它的引用压入堆栈。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(当然不完全是):
ldstr
将分配内存并从字面量创建一个新String
对象"abc"
stloc
将对该对象的引用存储在局部变量中a
ldloc
将该引用推入堆栈ldstr
将分配内存并从字面量创建一个新String
对象"xyz"
call
将调用堆栈System.String::Concat
上的这些对象String
System.String::Concat
会分解成几十条IL指令和内部调用。简而言之,它将检查两个字符串的长度并分配必要的内存量来存储连接结果,然后将这些字符串复制到新分配的内存中。stloc
将对新创建的字符串的引用存储在局部变量中b
这只是 C# 编译器通过允许字符串文字为您提供快捷方式。
如果您愿意,您可以通过任意数量的不同构造函数来实例化一个字符串。例如:
char[] chars = { 'w', 'o', 'r', 'd' };
string myStr = new String(chars);
根据 MS 文档,您不需要使用 new 命令来使用默认字符串构造函数。
然而,这确实有效。
char[] letters = { 'A', 'B', 'C' };
string alphabet = new string(letters);
字符串实际上是引用类型。该变量保存对内存中值的引用。因此,您只是将引用而不是值分配给对象。我建议你看一下 Pluralsight 的这个视频(你可以获得 14 天的免费试用期)
免责声明:我与 Pluralsight 没有任何关系。我是订阅者,我喜欢那里的视频
尽管 .net 中的一切都是对象,但仍有一些不需要实例化的原始类型(int、bool 等)。正如你在这里看到的,一个字符串是一个 4 字节的地址引用,指向一个可以扩展到 2GB 的向量/数组结构。请记住字符串是不可变类型,因此当您更改字符串时,您不会编辑现有变量,而是为文字值分配新内存,然后更改字符串指针以指向新的内存结构。希望有帮助
当您在内部使用文字创建字符串时,取决于您的程序集是否标有 NoStringInterning 标志,它看起来像:
String str = new String("samplestring");
// or with NoStringInterning
String str = String.Intern("samplestring");
在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#中它会是一样的。