修改后为什么字符串地址仍然相同

时间:2014-07-07 11:40:57

标签: c# .net

根据文档,类型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);
        }
    }
}

3 个答案:

答案 0 :(得分:3)

因为你正在编写局部变量c的地址,它在堆栈上的位置都是相同的。

请注意m_firstChar不是地址;它是第一个char 。在内部,代码使用相对于对象的第一个char的地址来访问数据,但是:m_firstChar将在这里报告'a'这两种情况,因为{{1是字符串中的第一个字符。

真正有趣:

'a'

现在"地址"不同的用于相同的字符串

答案 1 :(得分:3)

在这里获取字符串的地址

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

答案 2 :(得分:0)

尝试使用此函数获取字符串的地址:

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可能会移动字符串。