1

Convertion from Double[] src to Byte[] dst can be efficiently done in C# by fixed pointers:

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

How can I do the same for List src ? I.e. how can I get fixed pointer to array Double[] included in List ? Thanks.

Paul R
  • 208,748
  • 37
  • 389
  • 560
user536443
  • 11
  • 3

7 Answers7

2

I have used these helper methods before:

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

An example:

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();
jrob
  • 532
  • 1
  • 6
  • 16
1

not sure what you are intending, but I think ... you want System.Runtime.Interopservices.Marshal.StructToPtr.

Cheeso
  • 189,189
  • 101
  • 473
  • 713
1

You can always use the ToArray() method on the List<Double> object to get a Double[].

tvanfosson
  • 524,688
  • 99
  • 697
  • 795
1

You can use reflection to get the reference to the private T[] _items field, in the List instance.

Warning: In your code snippet, you need to make sure dstLength is the minimum of dst and src lengths in bytes, so that you don't try to copy more bytes than what are available. Probably you do so by creating dst with exactly the needed size to match the src, but your snippet doesn't make it clear.

Monoman
  • 721
  • 10
  • 12
0

Use the List<T>.ToArray() method and operate on the resulting array.

Femaref
  • 60,705
  • 7
  • 138
  • 176
  • I don't think this is desirable, as it implies a third array is created and values are copied to it, so the work and memory consumption is doubled. – Monoman Dec 09 '10 at 15:46
0

Why don't you just access the list as usual?

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

I haven't tested it thoroughly and i seldomly need unsafe code, but it seems to work fine.

Edit: here is another (imo preferable) solution, without unsafe code:

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;
    }
}
ollb
  • 1,453
  • 1
  • 11
  • 17
  • The conversion (double*)pres reside in the cycle. So will it be more efficiently to get the pointer to private T[] _items field in the List instance and convert it to (Byte*) only once ? – user536443 Dec 09 '10 at 17:19
  • @user536443 As far as I know the “conversion” is effectively a no-op (and thus has no impact on performance). The data in memory is just copied over and interpreted in a different way. Your code does it one byte at a time, mine will do it one double at a time. – ollb Dec 09 '10 at 17:31
  • @user536443 Accessing the list this way may be a bit more expensive than using a pointer (because of the range checks). Apart from that I think it is pretty much the same. If you >really< need the performance, then measure execution time. Anything else is speculative. And don't optimize if there is no need for it. – ollb Dec 09 '10 at 17:43
  • Thank you. I'l try out both solutions – user536443 Dec 10 '10 at 09:10
0

This might work, but you will have a data loss- content of the array will be 3 and 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>();
wizzardz
  • 5,664
  • 5
  • 44
  • 66