【问题标题】:How Unsafe.AsPointer<T>(ref T value) works?Unsafe.AsPointer<T>(ref T value) 如何工作?
【发布时间】:2018-07-30 17:30:04
【问题描述】:

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

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));
}

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

【问题讨论】:

  • 您可以在 C# 中创建和使用指针就好了。您需要做的就是启用不安全代码。很长一段时间以来,这一直是该语言的一部分。
  • 是的,但是当我尝试使用任何我收到警告的方法。
  • 为什么需要指向托管类型的指针?您只能读取/更改原始类型的字节 - 托管类型只是原始类型的集合。
  • @xxbbcc 我再次认为你(和亲密的选民)没有抓住重点。 OP 不是问它是好是坏,或者如何使用系统提供的方法,他们只是问如何某些系统类可能包含无效的 C# 代码。
  • @IvanStoev 你去。 :)

标签: c# pointers unsafe


【解决方案1】:

有问题的代码不是有效的 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 语言中引用它。

【讨论】:

    猜你喜欢
    • 2021-03-30
    • 1970-01-01
    • 2011-05-19
    • 2010-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-19
    • 1970-01-01
    相关资源
    最近更新 更多