【问题标题】:How to convert List<Double> to Byte[] in C#如何在 C# 中将 List<Double> 转换为 Byte[]
【发布时间】:2010-12-09 15:20:34
【问题描述】:

从 Double[] src 到 Byte[] dst 的转换 可以通过固定指针在 C# 中有效地完成:

fixed( Double* pSrc = src)
{
  fixed( Byte* pDst = dst)
  {
    Byte* ps = (Byte*)pSrc;
    for (int i=0; i < dstLength; i++)
    {
      *(pDst + i) = *(ps +i);
    }
  }
}

我怎样才能对 List src 做同样的事情? IE。如何获得指向数组 Double[] 的固定指针 包含在列表中? 谢谢。

【问题讨论】:

  • 我什至不知道存在这样的东西......
  • 我更好奇你为什么要通过指针来做到这一点?

标签: c# unsafe-pointers


【解决方案1】:

不确定您的意图,但我认为...您想要 System.Runtime.Interopservices.Marshal.StructToPtr.

【讨论】:

    【解决方案2】:

    您始终可以对List&lt;Double&gt; 对象使用ToArray() 方法来获取Double[]

    【讨论】:

      【解决方案3】:

      您可以使用反射来获取对 List 实例中私有 T[] _items 字段的引用。

      警告:在您的代码 sn-p 中,您需要确保 dstLength 是 dst 和 src 长度中的最小值(以字节为单位),这样您就不会尝试复制比实际更多的字节可用的。可能您通过创建具有与 src 匹配所需大小的 dst 来做到这一点,但您的 sn-p 并没有说清楚。

      【讨论】:

        【解决方案4】:

        我以前用过这些辅助方法:

        byte[] GetBytesBlock(double[] values)
        {
           var result = new byte[values.Length * sizeof(double)];
           Buffer.BlockCopy(values, 0, result, 0, result.Length);
           return result;
        }
        
        double[] GetDoublesBlock(byte[] bytes)
        {
           var result = new double[bytes.Length / sizeof(double)];
           Buffer.BlockCopy(bytes, 0, result, 0, bytes.Length);
           return result;
        }
        

        一个例子:

        List<double> myList = new List<double>(){ 1.0, 2.0, 3.0};
        
        //to byte[]
        var byteResult = GetBytesBlock(myList.ToArray());
        
        //back to List<double>
        var doubleResult = GetDoublesBlock(byteResult).ToList();
        

        【讨论】:

          【解决方案5】:

          使用List&lt;T&gt;.ToArray() 方法并对结果数组进行操作。

          【讨论】:

          • 我不认为这是可取的,因为这意味着创建了第三个数组并将值复制到其中,因此工作和内存消耗增加了一倍。
          【解决方案6】:

          这可能有效,但您会丢失数据 - 数组的内容将是 3 和 34。

              List<double> list = new List<double>();
              list.Add(Math.PI);
              list.Add(34.22);
          
              byte[] arr = (from l in list
                            select (byte)l).ToArray<byte>();
          

          【讨论】:

            【解决方案7】:

            你为什么不像往常一样访问列表?

            List<double> list = new List<double>();
            list.Add(Math.PI);
            list.Add(34.22);
            
            byte[] res = new byte[list.Count * sizeof(double)];
            
            unsafe
            {
                fixed (byte* pres = res)
                {
                    for (int i = 0; i < list.Count; i++)
                    {
                        *(((double*)pres) + i) = list[i];
                    }
                }
            }
            

            我没有彻底测试过它,我很少需要不安全的代码,但它似乎工作正常。

            编辑:这是另一个(imo 更可取的)解决方案,没有不安全的代码:

            int offset = 0;
            for (int i = 0; i < list.Count; i++)
            {
                long num = BitConverter.DoubleToInt64Bits(list[i]);
            
                for (int j = 0; j < 8; j++)
                {
                    res[offset++] = (byte)num;
                    num >>= 8;
                }
            }
            

            【讨论】:

            • 转换 (double*)pres 驻留在循环中。那么在 List 实例中获取指向私有 T[] _items 字段的指针并将其仅转换为 (Byte*) 一次会更有效吗?
            • @user536443 据我所知,“转换”实际上是无操作(因此对性能没有影响)。内存中的数据只是被复制并以不同的方式解释。你的代码一次一个字节,我的代码一次一个字节。
            • @user536443 以这种方式访问​​列表可能比使用指针更昂贵(因为范围检查)。除此之外,我认为它几乎是一样的。如果您>真的
            • 谢谢。我会尝试两种解决方案
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-03-25
            • 2011-08-26
            相关资源
            最近更新 更多