为什么字符串地址修改后仍然不变
本文关键字:字符串 地址 修改 为什么 | 更新日期: 2023-09-27 18:11:50
根据文档,类型System.String
在设计上是不可变的。所以,当尝试连接字符串等时,我们只需要获得对结果字符串的引用。但如果这是真的,为什么这段代码总是为两种情况返回相同的地址(当然,如果对象不是由GC移动的(:
using System;
using System.Reflection;
namespace StringImmutabilityCheck
{
class Program
{
private static unsafe void PrintAddress(string b)
{
var info = typeof(string).GetField("m_firstChar", BindingFlags.Instance | BindingFlags.NonPublic);
char value = (char)info.GetValue(b);
char* buffer = &value;
Console.WriteLine("Addres of {0} is {1}", b, (int)buffer);
}
static void Foo(ref string a)
{
a += "xxx";
}
static void Main()
{
string b = "aaaa";
PrintAddress(b);
Foo(ref b);
PrintAddress(b);
}
}
}
您不是在此处获取字符串的地址
char value = (char)info.GetValue(b); // 'value' is a local var
char* buffer = &value; // buffer points to local var, on the stack
Console.WriteLine("Addres of {0} is {1}", b, (int)buffer); // no it isn't
因为您正在写入局部变量c
的地址,它两次都在堆栈上的同一位置。
注意,m_firstChar
不是地址;它是第一个字符。在内部,代码使用相对于对象的第一个字符的地址来访问数据,但是:m_firstChar
将在这里为这两种情况报告'a'
,因为'a'
是字符串中的第一个字符串。
真正的乐趣:
[MethodImpl(MethodImplOptions.NoInlining)]
static void PassThru(string b)
{
PrintAddress(b);
}
...
PrintAddress(b);
PassThru(b);
现在,对于同一字符串,"地址"是不同的。
尝试使用此函数获取字符串的地址:
Func<string, int> getAddress = x =>
{
unsafe
{
fixed (char *p = x)
{
return (int)p;
}
}
};
然后这可以用来查看地址的变化:
var text = "Foo";
Console.WriteLine(getAddress(text));
text += "Bar";
Console.WriteLine(getAddress(text));
请注意,GC可能会在您使用时移动字符串。