【发布时间】:2015-08-10 23:17:55
【问题描述】:
考虑以下代码:
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;相反,我通过修改其状态或 mutating 字符串来更改其值。因此,.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# 语言设计者首先支持将字符串分配给指针。 (事实上,这是在 all the time 内部在 String 和 StringBuilder 中完成的,所以从技术上讲,你可以用它制作自己的 StringBuilder。)
那么,.NET 字符串真的应该被认为是不可变的吗?
【问题讨论】:
-
在使用公共 API 时它们是不可变的。如果您使用不安全的代码或反射来绕过该公共 API,则它们不是。
-
@MarcinJuraszek 指针是公共 API 的一部分,另见我的最后一段。
-
我说的是
string类的公共 API - 它公开的方法、属性。 -
致那些投反对票的人 - 请将鼠标悬停在上/下按钮上,并确保您投反对票的理由正确。不要仅仅因为您不同意或不推荐这种方法而投反对票。
-
它确实显示了研究成果,措辞清晰,并且包含有用的知识。这才是最重要的。
标签: c# .net string immutability