.NET引用数组

时间:2019-01-26 01:26:12

标签: c# reference

在.NET中,我们给了System.Span<T>,它可以直接引用连续内存。通常通过为其提供现有数组来构造它。但是,如果我希望能够创建对数组中不连续元素的引用数组,那么该怎么办?

例如,给定:

var array = new double[ 5 ] { 1, 2, 3, 4, 5 };
var span = new Span( array ); // Continuous references, [ 1, 2, 3, 4, 5 ]

如果我想使用array并创建一个“跨度”,该跨度可以具有不同的值排列,同时仍引用存储在数组中的值怎么办?如:

var discontinuous = new DiscontinuousSpan[3] { 
  (reference of array[1]), 
  (reference of array[0]), 
  (reference of array[4]) };

discontinuous[ 0 ]; // 2 (reference of array[1])
discontinuous[ 1 ]; // 1 (reference of array[0])
discontinuous[ 2 ]; // 5 (reference of array[4])

我看了Span<T>的文档,并了解它只是指向固定长度内存的指针。但是,在C#7.2中添加了对值类型的引用,不应该不连续地引用数组元素吗?我没有看到任何.NET类型的引用,因此我假设自己使用自定义值类型来实现类似的功能。

说明:主要目标是获得System.Numerics.Vector<T>的支持,以便我可以对不连续引用执行SIMD。

1 个答案:

答案 0 :(得分:0)

因此,您有一个带有数字的数组,并希望有对该数组段的单独引用。但是Span是一种特殊的值类型,无法传递。 因此,您必须存储信息以仅在需要时生成这些单独的跨度...

// Here we store index and length for each desired segment
var mySegments = new (int position, int length)[] { (17, 5), (48, 19), (79, 16) };

然后,当需要访问时...

double [100] Numbers = GetNumbersFromSomwhere();

public double[] GetSegment(int segmentIndex)
{
   var segment = mySegments[segmentIndex];
   var reference = new Span<double>(Numbers, segment.position, segment.length);
   return reference.ToArray();
}

但是,最后的ToArray()将实例化一个新的对象数组(生成GC压力)。因此,也许您可​​以将数据存储为字节数组(显然考虑了每个double的8个字节的长度),以生成独立的double跨度。后来,终于有了一个像这样的函数来读取特定的double值:

    // Converts a Span into a double
    // Requires using System.Runtime.CompilerServices.Unsafe
    public static double ToDouble(ReadOnlySpan<byte> value)
    {
        if (value.Length < sizeof(double))
            throw new ArgumentOutOfRangeException(nameof(value));
        return Unsafe.ReadUnaligned<double>(ref MemoryMarshal.GetReference(value));
    }

希望它对您的Vector(固定类型,我按此按钮)有帮助。