考虑以下代码:
unsafe
{
string foo = string.Copy("This can't change");
fixed (char* ptr = foo)
{
char* pFoo = ptr;
pFoo[8] = pFoo[9] = ' ';
}
Console.WriteLine(foo); // "This can change"
}
这将创建一个指向 foo
的第一个字符的指针,将其重新分配为可变的,并将字符 8 和 9 的位置更改为 ' '
。
请注意,我实际上从未重新分配过 foo
;相反,我通过修改它的状态或改变字符串来改变它的值。因此,.NET 字符串是可变的。
事实上,这非常有效,以至于下面的代码:
unsafe
{
string bar = "Watch this";
fixed (char* p = bar)
{
char* pBar = p;
pBar[0] = 'C';
}
string baz = "Watch this";
Console.WriteLine(baz); // Unrelated, right?
}
由于字符串文字驻留,将打印"Catch this"
。
这有很多适用的用途,例如:
string GetForInputData(byte[] inputData)
{
// allocate a mutable buffer...
char[] buffer = new char[inputData.Length];
// fill the buffer with input data
// ...and a string to return
return new string(buffer);
}
被替换为:
string GetForInputData(byte[] inputData)
{
// allocate a string to return
string result = new string('\0', inputData.Length);
fixed (char* ptr = result)
{
// fill the result with input data
}
return result; // return it
}
如果您在速度关键领域(例如编码)工作,这可能会节省潜在的巨大内存分配/性能成本。
我想您可能会说这不算数,因为它“使用 hack”使指针可变,但又是 C# 语言设计者首先支持将字符串分配给指针。 (事实上,这是在 String
和 StringBuilder
内部完成的 all the time,所以从技术上讲,您可以用它来制作自己的 StringBuilder。)
那么,.NET 字符串真的应该被认为是不可变的吗?
最佳答案
C# 语言规范的第 18.6 节(fixed
语句)专门解决了通过固定指针修改字符串的情况,并指出这样做会导致未定义的行为:
Modifying objects of managed type through fixed pointers can results in undefined behavior. For example, because strings are immutable, it is the programmer’s responsibility to ensure that the characters referenced by a pointer to a fixed string are not modified.
关于c# - .NET 字符串真的应该被认为是不可变的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31930705/