我遇到了"CorruptedString"(解决方案).以下是本书中的以下程序代码:
var s = "Hello";
string.Intern(s);
unsafe
{
fixed (char* c = s)
for (int i = 0; i < s.Length; i++)
c[i] = 'a';
}
Console.WriteLine("Hello"); // Displays: "aaaaa"
Run Code Online (Sandbox Code Playgroud)
为什么这个节目会显示"aaaaa"?我理解这个程序如下:
string.Intern(s)
实际上什么也没做,因为CLR保留了"Hello"字符串 - 它只返回保留的"Hello"字符串的地址(对象s具有相同的地址)据我了解实习池,它就像某种字符串字符串.或许我错过了什么?
Jar*_*lec 65
当您第一次使用"Hello"时,它会被插入到应用程序全局字符串存储中.基于您在unsafe
模式下执行的事实(更多关于unsafe
此处),您可以直接引用存储在最初为字符串值分配的位置中的数据s
,因此通过
for (int i = 0; i < s.Length; i++)
c[i] = 'a';
Run Code Online (Sandbox Code Playgroud)
你正在编辑内存中的内容.当它下次访问实习字符串的存储时,它将在内存中使用相同的地址,保存刚才更改的数据.没有,这是不可能的unsafe
.string.Intern(s);
在这里没有发挥作用; 如果你评论它,它的行为是一样的.
然后
Console.WriteLine("Hello"); // Displays: "aaaaa"
Run Code Online (Sandbox Code Playgroud)
.NET
查看是否有获取地址的条目,"Hello"
并且:您刚刚更新的地址"aaaaa"
.'a'
字符数由长度决定"Hello"
.
即使@Jaroslav Kadlec的回答是正确和完整的,我想补充一些关于代码行为的更多信息,为什么string.Intern(s);
在这种情况下没用.
实际上,.NET会自动为所有字符串文字执行字符串实习,这是通过使用一个特殊的表来完成的,该表存储对应用程序中所有唯一字符串的引用.
但是,重要的是要注意在编译阶段只有显式声明的字符串被实现.
请考虑以下代码:
var first = "Hello"; //Will be interned
var second = "World"; //Will be interned
var third = first + second; //Will not be interned
Run Code Online (Sandbox Code Playgroud)
当然,在某些情况下,我们希望在运行时实习一些字符串,这可以通过String.Intern
检查后完成String.IsInterned
.
所以回到OP的片段:
//...
var s = "Hello";
string.Intern(s);
//...
Run Code Online (Sandbox Code Playgroud)
在这种情况下string.Intern(s);
是无用的,因为它已经在编译阶段实习.