인스턴스의 고유 식별자를 얻는 방법이 있습니까?
GetHashCode()
동일한 인스턴스를 가리키는 두 개의 참조에 대해 동일합니다. 그러나 두 개의 서로 다른 인스턴스가 동일한 해시 코드를 얻을 수 있습니다.
Hashtable hashCodesSeen = new Hashtable();
LinkedList<object> l = new LinkedList<object>();
int n = 0;
while (true)
{
object o = new object();
// Remember objects so that they don't get collected.
// This does not make any difference though :(
l.AddFirst(o);
int hashCode = o.GetHashCode();
n++;
if (hashCodesSeen.ContainsKey(hashCode))
{
// Same hashCode seen twice for DIFFERENT objects (n is as low as 5322).
Console.WriteLine("Hashcode seen twice: " + n + " (" + hashCode + ")");
break;
}
hashCodesSeen.Add(hashCode, null);
}
디버깅 추가 기능을 작성 중이며 프로그램 실행 중에 고유 한 참조에 대한 일종의 ID를 가져와야합니다.
나는 이미 가비지 수집기 (GC)가 힙을 압축 할 때까지 고유 한 인스턴스의 내부 주소를 가져 왔습니다 (= 개체 이동 = 주소 변경).
스택 오버플로 질문 Object.GetHashCode ()의 기본 구현은 관련이있을 수 있습니다.
디버거 API를 사용하여 디버깅중인 프로그램의 개체에 액세스하기 때문에 개체는 내 통제하에 있지 않습니다. 내가 객체를 제어한다면 내 고유 식별자를 추가하는 것은 사소한 일입니다.
이미 본 개체를 조회 할 수 있도록 해시 테이블 ID-> 개체를 만들기위한 고유 ID를 원했습니다. 지금은 다음과 같이 해결했습니다.
Build a hashtable: 'hashCode' -> (list of objects with hash code == 'hashCode')
Find if object seen(o) {
candidates = hashtable[o.GetHashCode()] // Objects with the same hashCode.
If no candidates, the object is new
If some candidates, compare their addresses to o.Address
If no address is equal (the hash code was just a coincidence) -> o is new
If some address equal, o already seen
}
답변
참조 는 개체의 고유 식별자입니다. 나는 이것을 문자열 등과 같은 것으로 변환하는 방법을 모릅니다. 참조 값은 압축 중에 변경되지만 (당신이 본 것처럼) 모든 이전 값 A는 지금까지 값 B로 변경됩니다. 안전한 코드와 관련하여 여전히 고유 ID입니다.
관련된 개체가 제어하에있는 경우 선택한 ID (GUID, 정수 등)에 대한 참조에서 약한 참조 (가비지 수집 방지를 방지하기 위해)를 사용하여 매핑을 만들 수 있습니다 . 그러나 이는 일정량의 오버 헤드와 복잡성을 추가합니다.
답변
.NET 4 이상 만
모두들 좋은 소식입니다!
이 작업을위한 완벽한 도구는 .NET 4에 내장되어 있으며 ConditionalWeakTable<TKey, TValue>
. 이 수업 :
- 임의의 데이터를 사전과 같은 관리 객체 인스턴스와 연결하는 데 사용할 수 있습니다 (사전 은 아니지만).
- 메모리 주소에 의존하지 않으므로 힙을 압축하는 GC에 영향을받지 않습니다.
- 객체가 테이블에 키로 입력되었다고해서 객체를 유지하지 않으므로 프로세스의 모든 객체를 영원히 활성화하지 않고도 사용할 수 있습니다.
- 참조 동등성을 사용하여 객체 ID를 결정합니다. 이동, 클래스 작성자는이 동작을 수정할 수 없으므로 모든 유형의 객체에서 일관되게 사용할 수 있습니다.
- 즉석에서 채울 수 있으므로 객체 생성자 내부에 코드를 삽입 할 필요가 없습니다.
답변
체크 아웃 ObjectIDGenerator의 클래스? 이것은 당신이하려는 일과 Marc Gravell이 설명하는 것을 수행합니다.
ObjectIDGenerator는 이전에 식별 된 개체를 추적합니다. 개체의 ID를 요청하면 ObjectIDGenerator는 기존 ID를 반환할지 아니면 새 ID를 생성하고 기억 할지를 알고 있습니다.
ID는 ObjectIDGenerator 인스턴스의 수명 동안 고유합니다. 일반적으로 ObjectIDGenerator 수명은 자신을 생성 한 Formatter만큼 지속됩니다. 개체 ID는 지정된 직렬화 된 스트림 내에서만 의미가 있으며 직렬화 된 개체 그래프 내에서 다른 개체에 대한 참조가있는 개체를 추적하는 데 사용됩니다.
해시 테이블을 사용하여 ObjectIDGenerator는 어떤 ID가 어떤 개체에 할당되었는지 유지합니다. 각 개체를 고유하게 식별하는 개체 참조는 런타임 가비지 수집 힙의 주소입니다. 객체 참조 값은 직렬화 중에 변경 될 수 있지만 정보가 정확하도록 테이블이 자동으로 업데이트됩니다.
개체 ID는 64 비트 숫자입니다. 할당은 1부터 시작하므로 0은 유효한 개체 ID가 아닙니다. 포맷터는 값이 null 참조 (Visual Basic의 경우 Nothing) 인 개체 참조를 나타 내기 위해 0 값을 선택할 수 있습니다.
답변
RuntimeHelpers.GetHashCode()
도움이 될 수 있습니다 ( MSDN ).
답변
순식간에 자신 만의 것을 개발할 수 있습니다. 예를 들면 :
class Program
{
static void Main(string[] args)
{
var a = new object();
var b = new object();
Console.WriteLine("", a.GetId(), b.GetId());
}
}
public static class MyExtensions
{
//this dictionary should use weak key references
static Dictionary<object, int> d = new Dictionary<object,int>();
static int gid = 0;
public static int GetId(this object o)
{
if (d.ContainsKey(o)) return d[o];
return d[o] = gid++;
}
}
예를 들어 System.Guid.NewGuid ()와 같이 고유 ID로 원하는 것을 선택하거나 가장 빠른 액세스를 위해 단순히 정수를 선택할 수 있습니다.
답변
이 방법은 어떻습니까?
첫 번째 개체의 필드를 새 값으로 설정합니다. 두 번째 개체의 동일한 필드에 동일한 값이 있으면 동일한 인스턴스 일 수 있습니다. 그렇지 않으면 다르게 종료하십시오.
이제 첫 번째 개체의 필드를 다른 새 값으로 설정합니다. 두 번째 개체의 동일한 필드가 다른 값으로 변경된 경우 확실히 동일한 인스턴스입니다.
첫 번째 개체의 필드를 종료시 원래 값으로 설정하는 것을 잊지 마십시오.
문제?
답변
Visual Studio에서 고유 한 개체 식별자를 만들 수 있습니다. 조사 식 창에서 개체 변수를 마우스 오른쪽 단추로 클릭 하고 상황에 맞는 메뉴에서 개체 ID 만들기를 선택 합니다.
불행히도 이것은 수동 단계이며 코드를 통해 식별자에 액세스 할 수 있다고 생각하지 않습니다.