跨度和二维数组

时间:2018-10-11 00:42:54

标签: c# arrays .net multidimensional-array system.memory

是否可以将新的System.Memory Span struct与二维数据数组一起使用?

double[,] testMulti = 
    {
        { 1, 2, 3, 4 },
        { 5, 6, 7, 8 },
        { 9, 9.5f, 10, 11 },
        { 12, 13, 14.3f, 15 }
    };

double[] testArray = { 1, 2, 3, 4 };
string testString = "Hellow world";

testMulti.AsSpan(); // Compile error
testArray.AsSpan();
testString.AsSpan();

虽然testArray和testString具有AsSpan扩展名,但testMulti不存在此类扩展名。

Span的设计是否仅限于处理一维数据数组?
我找不到使用Span处理testMulti数组的明显方法。

5 个答案:

答案 0 :(得分:3)

您可以使用不受管理的内存创建一个type text。这样一来,您就可以随意切片和切丁

Span

完整演示

unsafe
{
    Span<T> something = new Span<T>(pointerToarray, someLength); 
}

输出

unsafe public static void Main(string[] args)
{
   double[,] doubles =  {
         { 1, 2, 3, 4 },
         { 5, 6, 7, 8 },
         { 9, 9.5f, 10, 11 },
         { 12, 13, 14.3f, 15 }
      };

   var length = doubles.GetLength(0) * doubles.GetLength(1) * sizeof(double);

   fixed (double* p = doubles)
   {
      var span = new Span<double>(p, length);
      var slice = span.Slice(6, 5);

      foreach (var item in slice)
         Console.WriteLine(item);
   }
}

其他选择是将其重新分配给一维数组,应对惩罚,并请勿通过

  • 7 8 9 9.5 10
  • 或p /直接调用BlockCopy并使用memcpy和指针
  • unsafe例如Cast<T>

对于大型数组,前2个将表现更好。

答案 1 :(得分:1)

所有跨度都是一维的,因为内存是一维的。

您当然可以将所有形式的结构映射到一维内存中,但是Span类不会为您完成此操作。但是您可以自己轻松地写一些东西,例如:

Slice()

棘手的部分是实现void OnGUI(){ GUI.Label(new Rect(0,0,0,0),userUpdate); } ,因为对于二维结构,语义有点模棱两可。您可能只能按一个维度对这种结构进行切片,因为按另一个维度对这种结构进行切片会导致内存不连续。

答案 2 :(得分:1)

正如 John Wu 已经提到的,跨度是一维的。 您当然可以自己实现 2D 跨度,但 Microsoft 已经为我们做到了。

查看文档 here
您可以找到寻址 nuget 包 here
该包还提供了一个 Memory2D。

 var arr = new int[,] { {1,2,3},{2,2,3},{3,2,3} };
 var spn = arr.AsSapn2D();
 // Now use it similar to a normal span
 // The access is of course a bit different since we are using a 2D data structure.
 Console.WriteLine(spn[0..2,..]);

答案 3 :(得分:0)

作为@saruman,我认为这是不可能的。

例如,您首先需要使用Fast way to convert a two dimensional array to a List ( one dimensional )Convert 2 dimensional array中显示的技术来获得一个新的单维数组。

答案 4 :(得分:0)

也许使用锯齿数组而不是多维数组会获得更大的成功。

double[][] testMulti = 
    {
        new double[] { 1, 2, 3, 4 },
        new double[] { 5, 6, 7, 8 },
        new double[] { 9, 9.5f, 10, 11 },
        new double[] { 12, 13, 14.3f, 15 }
    };

Span<double[]> span = testMulti.AsSpan(2, 1);
Span<double> slice = span[0].AsSpan(1, 2);

foreach (double d in slice)
    Console.WriteLine(d);

slice[0] = 10.5f;

Console.Write(string.Join(", ", testMulti[2]));

Console.ReadLine();

输出

9.5
10
9, 10.5, 10, 11