是否有可能获得C#对象地址的字符串表示?

时间:2012-11-06 09:06:17

标签: c# reference identity

我正在尝试调试多线程代码的一些奇怪的行为,我需要一些方法来可靠地跟踪对象标识。在C ++中,我只是获取对象地址并将它们转换为字符串,这样我就知道这两个地址是否属于同一个对象。

看起来像C#中的C ++对象地址的a reference is a full equivalent

我可以将引用转换为字符串地址表示吗?

3 个答案:

答案 0 :(得分:3)

您可以将引用转换为指针,然后转换为数字,但这不是在C#中跟踪对象的可靠方法,因为垃圾收集器可以随时更改引用。从参考中复制值后,您无法知道它仍然代表参考。

但是,您可以安全地比较参考。只要引用仍然是引用,垃圾收集器就会确保它是最新的。如果垃圾收集器移动一个对象,它会更新对它的所有引用。

因此,您可以安全地将引用用作对象的标识,只要您将其作为引用即可。您可以比较两个引用,看它们是否指向同一个对象。

如果将引用的值转换为其他表单,则会获得该引用当时所用内容的flash副本。虽然看到该值可能仍然有用,但它不是100%可靠,即仅仅因为两个引用的表示不同并不意味着它们不能指向同一个对象,因为引用可能在复制之间发生了变化第一个和第二个。

那就是说,这是你如何获得指向对象的指针并将其转换为IntPtr

string str = "asdfasdf";
IntPtr p;

unsafe {
  // tell GC not to move the object, so that we can use a pointer to it
  fixed (void* ptr = str) {
    // here the object stays in place
    // make an IntPtr from the pointer, so we can keep it outside the fixed block
    p = new IntPtr(ptr);
  }
  // now the object can move again
}

Console.WriteLine(p);

答案 1 :(得分:0)

在某种程度上,你可以:

GCHandle.Alloc(obj, GCHandleType.Pinned).AddrOfPinnedObject().ToString();

请不要将此作为调试多线程应用程序的方法。像Damien指出的那样。

答案 2 :(得分:0)

创建一个ConditionalWeakTable<Object,String>,每次看到表中没有的每个对象都会给它一些名称并将其存储在表中。然后,您可以毫无困难地使用该表打印出您之前看到的任何对象的名称。如果某个对象不再存在,那么表条目将会消失,因此无需担心该表填充了与早已被放弃的对象相关的信息。