我有一个我想以某种方式修改的字符串。例如:将其反转或将其翻转。
我发现最快的方法是使用不安全的块和指针。
例如:
unsafe
{
fixed (char* str = text)
{
*str = 'X';
}
}
我有什么理由不这样做吗?
答案 0 :(得分:16)
.Net框架要求字符串是不可变的。由于这一要求,它能够优化各种操作。
String interning是这个要求的一个很好的例子。为了加快一些字符串比较(并减少内存消耗),.Net框架维护一个指针字典,所有预定义的字符串将存在于此字典或您调用String.intern
方法的任何字符串中。当调用IL指令ldstr时,如果我们已经分配了字符串,它将检查实习字典并避免内存分配,注意:String.Concat不会检查实习字符串。
.net框架的这个属性意味着如果你开始直接使用字符串,你可以破坏你的实习表,反过来破坏对同一个字符串的其他引用。
例如:
// these strings get interned
string hello = "hello";
string hello2 = "hello";
string helloworld, helloworld2;
helloworld = hello;
helloworld += " world";
helloworld2 = hello;
helloworld2 += " world";
unsafe
{
// very bad, this changes an interned string which affects
// all app domains.
fixed (char* str = hello2)
{
*str = 'X';
}
fixed (char* str = helloworld2)
{
*str = 'X';
}
}
Console.WriteLine("hello = {0} , hello2 = {1}", hello, hello2);
// output: hello = Xello , hello2 = Xello
Console.WriteLine("helloworld = {0} , helloworld2 = {1}", helloworld, helloworld2);
// output : helloworld = hello world , helloworld2 = Xello world
答案 1 :(得分:14)
我有什么理由不这样做吗?
是的,非常简单:因为.NET依赖于字符串是不可变的这一事实。某些操作(例如s.SubString(0, s.Length)
)实际上返回对原始字符串的引用。如果现在修改了这个,那么所有其他引用也将如此。
最好使用StringBuilder
修改字符串,因为这是默认方式。
答案 2 :(得分:5)
这样说:如果另一个程序员在执行时决定用代码中的1替换0,你会有什么感觉?你会用你所有的假设来玩它。字符串也是如此。 每个人都希望它们是不可变的,并考虑到这一假设。如果你违反了这个规定,你可能会引入错误 - 而且它们真的难以追踪。
答案 3 :(得分:1)
哦亲爱的主啊。
1)因为该课程不是为了被篡改而设计的。
2)因为字符串在整个框架中被设计和预期是不可变的。这意味着其他人写的代码(包括MSFT)期望字符串的基础值永远不会改变。
3)因为这是过早优化而且是E V I L。
答案 4 :(得分:0)
同意StringBuilder,或者只是将你的字符串转换为字符/字节数组并在那里工作。另外,你给出了“upcasing”的例子 - String类有一个ToUpper方法,如果那个至少和你不安全的“upcasing”一样快,我会吃掉我的帽子。 / p>