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