__makeref 作为在 C# 中获取参考值的一种方式?
__makeref as a way to get a reference value in C#?
我看过这段代码,用来显示参考值:
static void Main(string[] args)
{
string s1 = "ab";
string s2 = "a"+"b";
string s3 = new StringBuilder("a").Append("b").ToString();
Console.WriteLine(GetMemoryAddress(s1));
Console.WriteLine(GetMemoryAddress(s2));
Console.WriteLine(GetMemoryAddress(s3));
}
static IntPtr GetMemoryAddress(object s1)
{
unsafe
{
TypedReference tr = __makeref(s1);
IntPtr ptr = **(IntPtr**) (&tr);
return ptr;
}
}
结果(如预期):
(我知道字符串实习在这里开始,但这不是问题)。
问题:
虽然看起来确实可以,
使用 __makeref
是否是在 c# 中获取参考值的正确方法?
或者在任何情况下这个 ^ 会失败....?
Although it seems that it does do the job, Does using __makeref
is this the right way of getting the reference value in c#?
在 C# 中没有 "right way" 这样做 - 这不是您想要尝试做的事情,但是:就 what 而言正在做——这本质上依赖于 TypedReference
的内部布局和类型强制;它会 work(只要 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 是否 "better" 而不是 __makeref
和类型强制等未记录和不受支持的语言功能:是一些争论的问题。希望纯学术辩论!
我看过这段代码,用来显示参考值:
static void Main(string[] args)
{
string s1 = "ab";
string s2 = "a"+"b";
string s3 = new StringBuilder("a").Append("b").ToString();
Console.WriteLine(GetMemoryAddress(s1));
Console.WriteLine(GetMemoryAddress(s2));
Console.WriteLine(GetMemoryAddress(s3));
}
static IntPtr GetMemoryAddress(object s1)
{
unsafe
{
TypedReference tr = __makeref(s1);
IntPtr ptr = **(IntPtr**) (&tr);
return ptr;
}
}
结果(如预期):
(我知道字符串实习在这里开始,但这不是问题)。
问题:
虽然看起来确实可以,
使用 __makeref
是否是在 c# 中获取参考值的正确方法?
或者在任何情况下这个 ^ 会失败....?
Although it seems that it does do the job, Does using
__makeref
is this the right way of getting the reference value in c#?
在 C# 中没有 "right way" 这样做 - 这不是您想要尝试做的事情,但是:就 what 而言正在做——这本质上依赖于 TypedReference
的内部布局和类型强制;它会 work(只要 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 是否 "better" 而不是 __makeref
和类型强制等未记录和不受支持的语言功能:是一些争论的问题。希望纯学术辩论!