我最近遇到一种情况,我需要建立一个通用的方法读取的数据类型出的一个字阵列。

我已经创建了以下类别:


public class DataStream
{
    public int Offset { get; set; }

    public byte[] Data { get; set; }

    public T Read<T>() where T : struct
    {
        unsafe
        {
            int dataLen = Marshal.SizeOf( typeof( T ) );
            IntPtr dataBlock = Marshal.AllocHGlobal( dataLen );


            Marshal.Copy( Data, Offset, dataBlock, dataLen );


            T type = *( ( T* )dataBlock.ToPointer() );

            Marshal.FreeHGlobal( dataBlock );

            Offset += dataLen;

            return type;
        }
    }
}

现在,de分配问题放在一边,这个代码没有编纂这个信息:

Cannot take the address of, get the size of, or declare a pointer to a managed type ('T')

其中,似乎很奇怪因为你应该能够做到的上述行动的基础上 where T : struct 制约因素的方法。

如果这代码是可怕的错误,是否有任何简单的方式采取了一系列的字节,并将它们转换成'T'类型?

谢谢!

有帮助吗?

解决方案

而不是试图通过指针操作要做到这一点,你应该切换您的代码中使用的 Mashal.PtrToStructure 。此方法是专门为这种情况设计的。

其他提示

由于答复中已经给出的,让我解释为什么你的原始代码没有为你工作:

其中,似乎很奇怪因为你应该能够做到的上述行动的基础上在T:结构上的约束方法。

不是真的。你可以拥有原始指向 非托管的类型.这个定义如下的C#语言规范(18.2):

不像引用(数值的基准类型),指针不是跟踪通过的垃圾收集器—垃圾回收已经没有知识的指标和数据来,他们一点。由于这个原因一指针是不允许的要点参考或结构,包含参考文献,所指的类型的指针必须是一个 非管理型.一个 非管理型 是任何类型,不是一个参考型并不包含参考型领域,在任何级别的嵌套。换句话说, 非管理型 是下列之一:

  • sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal, 或 bool.
  • 任何 枚举型.
  • 任何 指针型.
  • 任何用户定义的 结构类型 包含的领域 非托管的类型 只。

所以有一些限制,和一个通用的方法, T:struct 可能会或可能不符合他们的任何具体的实例,因此构建喜欢 T* 是非法的。这将是很好有一个特别的通用类型参数的约束复盖非托管的类型,但是因为它的立场,没有一个在CLR。

在一个点上,我写 解释如何做到这点,但很多时候比Marshal.PtrToStructure更快。该代码示例使用动态代码生成与通用类型T从比特流拷贝到/

假设:

  • 顺序或明确的结构(否则非常糟糕的主意)
  • 正确的数据尺寸(你应该预先检查和扔)

unsafe TStruct BytesToStructure<TStruct>(byte[] data) where TStruct : struct
{
    fixed (byte* dataPtr = data)
        return (TStruct)Marshal.PtrToStructure(new IntPtr(dataPtr), typeof(TStruct));
}

unsafe byte[] StructureToBytes<TStruct>(TStruct st) where TStruct : struct
{
    var bytes = new byte[Marshal.SizeOf(st)];
    fixed (byte* ptr = bytes) Marshal.StructureToPtr(st, new IntPtr(ptr), true);
    return bytes;
}

我写这一段时间回做同样的事情: http://www.codeproject.com/Articles/33713/Generic-BinaryReader-and-BinaryWriter-Extensions

您将有一个C ++ / CLI项目添加到您的Visual Studio解决方案虽然。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top