C#fill随机数据的结构数组

时间:2017-09-06 10:37:48

标签: c# random struct

出于测试目的,我想做以下事情:

class ArrayOfStructWithRandomData<T> where T : struct {
  private T[] array;

  ArrayOfStructWithRandomData() {
    array = new T[1000000];
    InitializeArrayToRandomData();
  }
}

如何在不使用'unsafe'关键字的情况下实现InitializeArrayToRandomData()?

一个想法是使用Marshal.AllocHGlobal(Marshal.SizeOf(typeof(T)) * 1000000)分配一大块非托管内存,然后使用Marshal.Copy(Byte[], Int32, IntPtr, Int32)用随机数据填充该内存,然后使用类似

的内容
static T[] GetArrayFromNativePointer<T>(IntPtr unmanaged_memory, int length) {
  T[] result = new T[length];
  if (IntPtr.Size == 4) {
    int size = Marshal.SizeOf(typeof(T));

    // 32-bit system.
    for (int i = 0; i < result.Length; i++) {
      result[i] = (T)Marshal.PtrToStructure(unmanaged_memory, typeof(T));
      unmanaged_memory= new IntPtr(unmanaged_memory.ToInt32() + size);
    }
  } else {
    long size = Marshal.SizeOf(typeof(T));

    // Probably 64-bit system.
    for (int i = 0; i < result.Length; i++) {
      result[i] = (T)Marshal.PtrToStructure(unmanaged_memory, typeof(T));
      unmanaged_memory= new IntPtr(array.ToInt64() + size);
    }
  }
  return result;
}

有更好的方法吗?

4 个答案:

答案 0 :(得分:2)

如果您想关闭特定方法或属性的优化,可以使用

[MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)]

这将阻止编译器以及稍后的JITter优化或内联该方法。然后,您可以继续使用默认值,而无需编译器最终优化。

答案 1 :(得分:0)

我不确定你是否正在搜索但是你可以在初始化它的结构中使用隐式运算符,就像这个例子一样:

public static implicit operator MyStruct(T[] value) {
    return new MyStruct() { structValue = value, Structlength = value.Length };
  }

答案 2 :(得分:0)

这个怎么样:

        [StructLayout(LayoutKind.Sequential)]
        struct Root
        {
            [MarshalAs(UnmanagedType.Struct, SizeConst = 1000000)]
            Child[] children { get; set; }
        }
        struct Child
        {
            int property1 { get; set; }
            int property2 { get; set; }
            int property3 { get; set; }
            int property4 { get; set; }
            int property5 { get; set; }
            int property6 { get; set; }
        }

答案 3 :(得分:0)

如果您希望从非托管内存复制到托管阵列,最有效的方法是使用Marshal.Copy固定阵列并进行复制。

void BlitFromByteArrayToArray(byte[] src, T[] dst)
{
    Debug.Assert(src.Length == dst.Length * Marshal.SizeOf(typeof(T)));

    GCHandle handle = GCHandle.Alloc(dst, GCHandleType.Pinned);
    try
    {
        Marshal.Copy(src, 0, handle.AddrOfPinnedObject(), src.Length);
    }
    finally
    {
        handle.Free();
    }
}

请注意,我不是分配非托管内存,而是使用随机数据填充非托管内存,而是使用字节数组对其进行编码以保存源随机数据。没有必要为此使用非托管内存。

请注意,整个方法确实假设T是一种blittable类型。

最后,如果效率很重要,最好做以下事情:

  1. 分配您的托管数组。
  2. 使用GCHandle.Alloc固定数组。
  3. 将随机数据写入AddrOfPinnedObject返回的非托管数组。
  4. 取消固定阵列。
  5. 这样可以避免需要写入一个缓冲区然后复制到另一个缓冲区。