Unsafe.AsPointer <t>(参考T值)如何工作?

时间:2018-07-30 17:30:05

标签: 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;
}

也在其他类似的API中:

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

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

1 个答案:

答案 0 :(得分:4)

有问题的代码不是有效的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

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

将托管实例加载到堆栈上,然后将其作为无符号指针值简单地返回。

如果要重新创建此行为,可以-只需用IL编写DLL并进行编译,然后从任何其他支持指针的.NET语言中引用它即可。