【问题标题】:Is it possible to get a pointer to a boxed unmanaged value type?是否有可能获得指向装箱的非托管值类型的指针?
【发布时间】:2022-11-23 10:54:11
【问题描述】:

是否有可能获得一个指向装箱的非托管值类型的指针,而无需编写一个大型 switch 语句来为每个支持的类型执行强制转换?就像是:

object val;         // Contains a boxed unmanaged value, such as int, long, byte, etc.
void* ptr = &val;   // Obviously does not compile
DoStuffWithPointer(ptr);

代替

object val;   // Contains a boxed unmanaged value, such as int, long, byte etc.
if (val.GetType() == typeof(byte)) 
{
    var typedValue = (byte)value;
    DoStuffWithPointer(&typedValue);
}
else if (val.GetType() == typeof(short)) 
{
    var typedValue = (short)value;
    DoStuffWithPointer(&typedValue);
}
else 
    // ... and so on

顺便提一句。我知道指针指向堆栈上的局部变量,一旦函数返回就会失效。没关系。

【问题讨论】:

  • 为什么首先需要指针?
  • 您可以使用Unsafe.AsPointer<T>。应该做你正在寻找的东西。

标签: c# pointers boxing


【解决方案1】:

您可以使用ref T Unsafe.Unbox<T>(object)获取管理指向装箱值的指针 (ref T)。 将非托管指针 (T*) 获取到盒装值实际上是与 GC 的竞争,除非您已使用 GCHandle 固定了盒,并且可以使用 T* Unsafe.AsPointer<T>(ref T) 完成。

(!) 仔细阅读评论Unsafe.Unbox 部分:不允许更改只读盒装值,例如readonly struct 和原语,请改用class StrongBox<T>

然而,开发人员不得改变返回的引用,除非他们 确定 T 是可变结构类型。例如,因为 Int32 等数字基元不是可变结构类型,

顺便提一句。我知道指针指向堆栈上的局部变量,一旦函数返回就会失效。没关系。

似乎您可以将它从盒子处理到堆栈,然后您可以使用简洁的开关语法

    switch (val)
    {
        case int typedValue: DoStuffWithPointer(&typedValue); break;
        case byte typedValue: DoStuffWithPointer(&typedValue); break;
        //...
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-09
    • 1970-01-01
    相关资源
    最近更新 更多