Хотя кажется, что он делает свою работу, использование __makeref
является ли правильным способом получения эталонного значения в c #?
Не существует «правильного» способа сделать это в C # - это не то, что вы должны попробовать и сделать, но: с точки зрения того, что делает - это, по сути, полагается на внутреннем макете TypedReference
и приведении типа; это будет работать (до тех пор, пока TypedReference
не изменится внутренне - например, изменяется порядок полей Type
и Value
), но ... это неприятно.
Существует более прямой подход; в IL вы можете молча преобразовать из управляемого указателя в неуправляемый указатель . Это означает, что вы можете сделать что-то неприятное, например:
unsafe delegate void* RefToPointer(object obj);
static RefToPointer GetRef { get; } = MakeGetRef();
static RefToPointer MakeGetRef()
{
var dm = new DynamicMethod("evil", typeof(void*), new[] { typeof(object) });
var il = dm.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ret);
return (RefToPointer)dm.CreateDelegate(typeof(RefToPointer));
}
и теперь вы можете просто сделать:
var ptr = new IntPtr(GetRef(o));
Console.WriteLine(ptr);
Это ужасно , и вы никогда не должны этого делать - и, конечно, GC может перемещать вещи, когда вы не смотрите (или даже когда вы смотрите), но ... это работает.
Вопрос о том, является ли ref-emit «лучше», чем недокументированные и неподдерживаемые языковые функции, такие как __makeref
и приведение типов: является вопросом некоторых дискуссий. Надеюсь чисто академические дебаты!