You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#中如何查看字符串对象地址及变量地址差异原因?

问题解答

为什么word1和word2的变量地址不同,但object.ReferenceEquals返回true?

你混淆了变量的地址和变量指向的对象的地址:

  • &word1 获取的是局部变量word1本身在栈上的存储地址,word1和word2是两个独立的局部变量,栈上的存储位置自然不同,所以输出的addr1和addr2不一样。
  • object.ReferenceEquals(a, b) 判断的是两个变量指向的是否是同一个堆对象。因为C#对字符串常量有**字符串驻留(String Interning)**优化:编译时会把相同的字符串常量存入字符串常量池,运行时多个指向该常量的变量会复用同一个堆对象,所以word1和word2的引用指向同一个"Hello"对象,ReferenceEquals返回true。

如何查看字符串对象本身的地址?

有两种常用方法,根据是否允许unsafe代码选择:

方法1:使用unsafe代码直接获取对象地址

通过Unsafe.AsPointer获取变量存储的对象引用(即堆对象地址),不需要取变量本身的地址:

using System;
using System.Runtime.CompilerServices;

unsafe void Method()
{
    string word1 = "Hello";
    string word2 = "Hello";

    // 获取变量指向的字符串对象的堆地址
    ulong objAddr1 = (ulong)Unsafe.AsPointer(ref word1);
    ulong objAddr2 = (ulong)Unsafe.AsPointer(ref word2);

    Console.WriteLine($"word1指向的对象地址:{objAddr1}");
    Console.WriteLine($"word2指向的对象地址:{objAddr2}"); // 会和objAddr1相同
}

方法2:使用GCHandle(无需unsafe代码)

通过GCHandle固定对象并获取其地址:

using System;
using System.Runtime.InteropServices;

void Method()
{
    string word1 = "Hello";
    string word2 = "Hello";

    // 获取word1指向的对象地址
    GCHandle handle1 = GCHandle.Alloc(word1, GCHandleType.Pinned);
    IntPtr addr1 = handle1.AddrOfPinnedObject();
    Console.WriteLine($"word1指向的对象地址:{addr1}");
    handle1.Free();

    // 获取word2指向的对象地址
    GCHandle handle2 = GCHandle.Alloc(word2, GCHandleType.Pinned);
    IntPtr addr2 = handle2.AddrOfPinnedObject();
    Console.WriteLine($"word2指向的对象地址:{addr2}"); // 会和addr1相同
    handle2.Free();
}

补充说明:你代码里object.ReferenceEquals(aaa, bbb)返回false,是因为int是值类型,调用ReferenceEquals时会把它们分别装箱成两个独立的object对象,所以引用不相等。

内容的提问来源于stack exchange,提问作者UZBsdkbr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 20:31:05