本文介绍了将字节数组复制到C#中的class/struct中的各个字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在下面的示例C#代码中,我有一个从套接字读取的字节数组.我想将数据解析到"exampleClass"的各个字段中(前8个字节存入64位变量"field1",接下来4个字节存入32位变量"field2",等等)

In the example C# code below, I have a byte array which has been read from a socket. I want to parse the data into the various fields of 'exampleClass' (first 8 bytes into the 64-bit variable 'field1', next 4 bytes into 32-bit variable 'field2', etc.)

using System;
namespace CsByteCopy
{
  class Program
  {
    class ExampleClass
    {
      public UInt64 field1;
      public UInt32 field2;
      public UInt16 field3;
      public byte[] field4 = new byte[18];
    }

    static void Main(string[] args)
    {
      byte[] exampleData =
      {
        // These 8 bytes should go in 'field1'
        0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
        // These 4 bytes should go in 'field2'
        0x08,0x09,0x0A,0x0B,
        // These 2 bytes should go in 'field3'
        0x0C,0x0D,
        // These 18 * 1 bytes should go in 'field4'
        0x0E,0x0F,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
      };

      ExampleClass exampleClass = new ExampleClass();
      // Perform copy
    }
  }
}

自上次使用C以来已经有很长时间了,但是如果我没记错的话,我也许可以通过一次调用memcpy()来填充类中的所有字段而摆脱困境. 在C#中填充"exampleClass"字段的最有效方法是什么?

It's been a long time since I last used C, but if I recall correctly, I might have been able to get away with a single memcpy() call to populate all the fields in the class. What's the most efficient way of populating the fields of 'exampleClass' in C#?

推荐答案

您有很多选择,而最终选择最好的选择通常取决于程序需要/可以处理的内容以及所需的速度.有很多文章解释了用数据填充类或结构的不同方法.

You have a lot of options, the one that turns out the best usually depends on what your program needs/can handle and exactly how much speed you want. There are a lot of articles that explain the different ways you can populate a class or a struct with data.

二进制序列化是一种方法.这需要您编写一个自定义的序列化器,这非常容易. 有关MSDN的文章表明这并不难.

Binary Serialization is one way. That requires you write a custom serializer, which is fairly easy. An MSDN article regarding that shows it's not too difficult.

您可以编写一个私有构造器,该构造器采用字节数组并使用 BinaryReader BitConverter 类从字节数组中读取(对于BinaryReader,您必须将其包装在MemoryStream中)或将字节数组的各个部分转换为所需的值(BitConverter).对于BitConverter,您还需要使用Buffer.BlockCopy将字节数组的剩余数据复制到类中的字节数组字段中

You can write a private constructor that takes in the byte array and uses a BinaryReader or the BitConverter class to read from the byte array (you'd have to wrap it in a MemoryStream for BinaryReader) or to simply convert sections of the byte array to the values you need (BitConverter). In the case of BitConverter you would also need to use Buffer.BlockCopy to copy the remaining data of the byte array to the byte array field in your class

第三种方法(通常也是最快的方法)是将类转换为结构,并使用不安全的代码将字节数组转换为该结构.像这样:

A third way, also generally the fastest way, is to convert your class to a struct and use unsafe code to cast the byte array as that struct. Something like this:

unsafe struct ExampleClass
{
   public ulong field1;
   public uint field2
   public ushort field3
   public fixed byte field4[18];

   public static ExampleClass ReadStruct(byte[] data)
   {
       fixed (byte* pb = &data[0])
       {
           return *(ExampleClass*)pb;
       }
   }
}

当然,以上代码仅在可以使用不安全代码的情况下才有效.此外,将类转换为struct可能也不是您想要的.在大多数情况下,结构是通过值传递给函数的,因此调用方法将复制整个结构(在这种情况下为32字节),而不是传递引用(4或8字节,具体取决于CPU体系结构)和 can 降低程序效率.按值传递结构有一些例外,您可以为此使用自己喜欢的搜索引擎.

Of course, the above code is only valid if you can use unsafe code. Furthermore, converting the class to a struct may also not be what you're looking for. In most cases, structs are passed by value to functions, so that calling methods copies the entire struct (in this case 32 bytes) instead of passing a reference (4 or 8 bytes, depending on CPU architecture) and can reduce the efficiency of your program. There are exceptions to structs being passed by value, and you can use your favorite search engine for that.

如果您不能使用不安全的代码,也可以使用Marshal.PtrToStructure与上面的代码相同,但速度要慢10倍左右.您还需要使用MarshalAs属性来指定数组的大小,而不是使用fixed关键字(这是不安全的).到那时,您最好使用BinaryReader/BitConverter,因为它将比编组类更快.

If you can't use unsafe code, there is also Marshal.PtrToStructure which will do the same as the above code, but about 10 times slower. You would also need to use the MarshalAs attribute to specify the size of the array, instead of using the fixed keyword (which is unsafe). At that point, you might as well use the BinaryReader/BitConverter, as it will be faster than the marshal class.

这篇关于将字节数组复制到C#中的class/struct中的各个字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-29 09:41