我在接受采访时被问到这个问题:字符串是引用类型还是值类型.
我说它是一个引用类型.然后他问我为什么不在初始化字符串时使用new运算符?我说因为c#语言有一个更简单的语法来创建一个字符串,编译器会自动将代码转换为对System.String类的construcor的调用.
这个答案是否正确?
Dar*_*rov 31
字符串是不可变的引用类型.有ldstr IL指令允许将新对象引用推送到字符串文字.所以当你写:
string a = "abc";
Run Code Online (Sandbox Code Playgroud)
编译器测试文件是否"abc"已在元数据中定义,如果没有声明它.然后它将此代码转换为以下IL指令:
ldstr "abc"
Run Code Online (Sandbox Code Playgroud)
这基本上使a局部变量指向元数据中定义的字符串文字.
所以我会说你的答案不太正确,因为编译器没有把它转化为对构造函数的调用.
Inc*_*ito 28
不完全正确的答案.字符串是"特殊"引用类型.他们是不变的.编译器在内部执行某些操作是正确的,但它不是构造函数调用.它调用ldstr,它将新对象引用推送到存储在元数据中的字符串文字.
示例C#代码:
class Program
{
static void Main()
{
string str;
string initStr = "test";
}
}
Run Code Online (Sandbox Code Playgroud)
这是IL代码
.method private hidebysig static void Main() cil managed
{
.entrypoint
// Code size 8 (0x8)
.maxstack 1
.locals init ([0] string str,
[1] string initStr)
IL_0000: nop
IL_0001: ldstr "test"
IL_0006: stloc.1
IL_0007: ret
} // end of method Program::Main
Run Code Online (Sandbox Code Playgroud)
你可以看到ldstr上面的电话.
由于字符串的不变性,更可能只保留不同/唯一的字符串.所有字符串都保存在哈希表中,其中键是字符串值,值是对该字符串的引用.每当我们有一个新的字符串CLR检查时,哈希表中就已存在这样的字符串.如果没有,则分配新内存并将引用设置为此现有字符串.
您可以运行此代码来检查:
class Program
{
static void Main()
{
string someString = "abc";
string otherString = "efg";
// will retun false
Console.WriteLine(Object.ReferenceEquals(someString, otherString));
someString = "efg";
// will return true
Console.WriteLine(Object.ReferenceEquals(someString, otherString));
}
}
Run Code Online (Sandbox Code Playgroud)
Guf*_*ffa 12
好吧,编译器具有简化字符串创建的特殊语法是正确的.
关于编译器产生对构造函数的调用的部分并不正确.应用程序启动时会创建字符串文字,因此在使用字符串文字时,它只是对已存在对象的引用的赋值.
如果在循环中指定字符串文字:
string[] items = new string[10];
for (int i = 0; i < 10; i++) {
items[i] = "test";
}
Run Code Online (Sandbox Code Playgroud)
它不会为每次迭代创建一个新的字符串对象,它只会将相同的引用复制到每个项目中.
关于字符串文字的另外两个值得注意的事情是,编译器不会创建重复项,并且如果将它们连接起来,它会自动组合它们.如果您多次使用相同的文字字符串,它将使用相同的对象:
string a = "test";
string b = "test";
string c = "te" + "st";
Run Code Online (Sandbox Code Playgroud)
变量a,b并且c都指向同一个对象.
字符串类还包含可以使用的构造函数:
string[] items = new string[10];
for (int i = 0; i < 10; i++) {
items[i] = new String('*', 42);
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,您将实际获得十个单独的字符串对象.