Reputation: 170489
I'm trying to debug some weird behavior of multithreaded code and I need some way to reliably track object identity. In C++ I'd just get object addresses and convert them into strings and that way I'd know if the two addresses were of the same object or not.
Looks like a reference is a full equivalent of a C++ object address in C#.
Can I convert a reference into a string address representation?
Upvotes: 4
Views: 510
Reputation: 81169
Create a ConditionalWeakTable<Object,String>
, and any time you see each object that isn't in the table give it some sort of name and store it in the table. You may then without difficulty print out a name for any object you've seen before simply by using the table. If an object ceases to exist, the table entry will evaporate, so there's no need to worry about the table filling up with information related to objects that have long since been abandoned.
Upvotes: 0
Reputation: 700362
You can convert a reference to a pointer, and then to a number, but that's not a reliable way to track an object in C#, as the garbage collector can change a reference at any time. Once you copy the value from the reference, you can't know that it still represents the reference.
However, you can safely compare references. As long as the reference is still a reference, the garbage collector makes sure that it's up to date. If the garbage collector moves an object, it updates all references to it.
So, you can safely use the reference as identity for an object, as long as you keep it a reference. You can compare two references to see if they point to the same object or not.
If you convert the value of a reference to a different form, you get a flash copy of what the reference was at that moment. While it may still be useful to see that value, it's not 100% reliable, i.e. just because the representation of two references are different doesn't mean that they can't point to the same object, because the references could have changed between copying the first one and the second one.
That said, here's how you can get a pointer to an object and convert it to an 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);
Upvotes: 3
Reputation: 706
In a way, you can:
GCHandle.Alloc(obj, GCHandleType.Pinned).AddrOfPinnedObject().ToString();
Please do not use this as a way to debug your multi-threaded app. Do as Damien pointed.
Upvotes: 0