Unsafe.AsPointer<T>(ref T value) 如何工作?

Fre*_* L. 3 c# pointers unsafe

在 C# 中,您不应该能够创建指向托管类型的指针,但通过此 API,您可以使用Unsafe.AsPointer<T>.

https://www.nuget.org/packages/System.Runtime.CompilerServices.Unsafe/

我使用 ILSpy 查看源代码,看到了以下内容:

[MethodImpl(MethodImplOptions.AggressiveInlining)]
[System.Runtime.Versioning.NonVersionable]
public unsafe static void* AsPointer<T>(ref T value)
{
    return &value;
}
Run Code Online (Sandbox Code Playgroud)

还有其他类似的API:

//Unity.Collections.LowLevel.Unsafe.UnsafeUtility
public unsafe static T ReadArrayElement<T>(void* source, int index)
{
    return *(T*)((byte*)source + index * sizeof(T));
}
Run Code Online (Sandbox Code Playgroud)

这是如何运作的以及如何复制这种行为?

xxb*_*bcc 7

有问题的代码不是有效的 C# 代码,并且可能最初不是用 C# 编写的。您看到的是 ILSpy 的底层代码的 C# 表示形式 - C# 语法能够表示这一点,因为它只是一条编译器规则,表明您无法获取指向托管类型的指针。

我的猜测(事实上我不知道这一点)有问题的代码首先是用 IL 编写的 - 如果你将其反编译为 IL,你可以看到它是一个微不足道的位:

.method public hidebysig static 
    void* AsPointer<T> (
        !!T& 'value'
    ) cil managed flag(0100) 
{
    .custom instance void 
        System.Runtime.Versioning.NonVersionableAttribute::.ctor() = (
        01 00 00 00
    )
    // Method begins at RVA 0x2190
    // Code size 3 (0x3)
    .maxstack 1

    IL_0000: ldarg.0
    IL_0001: conv.u
    IL_0002: ret
} // end of method Unsafe::AsPointer
Run Code Online (Sandbox Code Playgroud)

(这是来自 System.Runtime.CompilerServices.Unsafe.dll。)

托管实例被加载到堆栈中,然后它只是作为无符号指针值返回。

如果您想重新创建此行为,您可以简单地用 IL 编写 DLL 并编译它,然后从任何其他支持指针的 .NET 语言引用它。