// Formats a string that *should* uniquely identify an object through multiple snapshots and multiple sessions
        public string FormatUniqueString(ObjectData od)
        {
            switch (od.dataType)
            {
            case ObjectDataType.Type:
                return(m_Snapshot.typeDescriptions.typeDescriptionName[od.managedTypeIndex]);

            case ObjectDataType.Global:
                return("<global>");

            case ObjectDataType.NativeObject:
                return(FormatInstanceId(od.codeType, m_Snapshot.nativeObjects.instanceId[od.nativeObjectIndex]));

            case ObjectDataType.Object:
            {
                int index = od.GetManagedObjectIndex(m_Snapshot);
                if (index >= 0)
                {
                    int nativeIndex = m_Snapshot.CrawledData.ManagedObjects[index].NativeObjectIndex;
                    if (nativeIndex >= 0)
                    {
                        return(FormatInstanceId(CodeType.Managed, m_Snapshot.nativeObjects.instanceId[nativeIndex]));
                    }
                    ulong ptr;
                    if (od.TryGetObjectPointer(out ptr))
                    {
                        return(FormatPointer(ptr));
                    }
                }
                goto default;
            }

            case ObjectDataType.Unknown:
                return("<uninitialized type>");

            default:
            {
                if (od.IsField())
                {
                    int   offset = m_Snapshot.fieldDescriptions.offset[od.fieldIndex];
                    ulong objPtr = od.GetObjectPointer(m_Snapshot);
                    return(FormatPointerAndOffset(objPtr, offset));
                }
                else if (od.IsArrayItem())
                {
                    ulong objPtr = od.GetObjectPointer(m_Snapshot);
                    return(FormatterPointerAndIndex(objPtr, od.arrayIndex));
                }
                else
                {
                    ulong ptr;
                    if (od.TryGetObjectPointer(out ptr))
                    {
                        return(FormatPointer(ptr));
                    }
                    return(od.GetUnifiedObjectIndex(m_Snapshot).ToString());
                }
            }
            }
        }
        // Formats "{field=value, ...}"
        public string FormatObjectBrief(ObjectData od, IDataFormatter formatter, bool objectBrief)
        {
            if (objectBrief)
            {
                string result = "{";
                var    iid    = od.GetInstanceID(m_Snapshot);
                if (iid != ObjectData.InvalidInstanceID)
                {
                    result += "InstanceID=" + iid;
                }
                int fieldCount = od.GetInstanceFieldCount(m_Snapshot);
                if (fieldCount > 0)
                {
                    if (iid != ObjectData.InvalidInstanceID)
                    {
                        result += ", ";
                    }
                    var    field = od.GetInstanceFieldByIndex(m_Snapshot, 0);
                    string k     = field.GetFieldName(m_Snapshot);
                    string v     = Format(field, formatter, false);
                    if (fieldCount > 1)
                    {
                        return(result + k + "=" + v + ", ...}");
                    }
                    else
                    {
                        return(result + k + "=" + v + "}");
                    }
                }
                else
                {
                    return(result + "}");
                }
            }
            ulong ptr;

            if (od.TryGetObjectPointer(out ptr))
            {
                return(FormatPointer(ptr));
            }
            return("{...}");
        }