C# 在不复制的情况下获取数组子集,就像在C中使用指针一样

C# 在不复制的情况下获取数组子集,就像在C中使用指针一样,c#,arrays,C#,Arrays,我有一个api调用,需要获取一个字节[]作为参数,我的数据已经在字节[]中。问题是我想把这个缓冲区分成小块发送 缓慢的解决方案是将阵列数据复制到新阵列。但我不想这样做,因为复制是不必要的。我只需要一个字节[]-指针,我可以在缓冲区中移动它。像C或C++一样……/P> 下面是一个伪代码示例: ArrayOriginal = { 0, 1, 2, 3, 4, ... 100 } ArrayFirstChunk={0,1,2}(指向原始数组中第一个元素的指针) ArraySecondChunk={3

我有一个api调用,需要获取一个
字节[]
作为参数,我的数据已经在
字节[]
中。问题是我想把这个缓冲区分成小块发送

缓慢的解决方案是将阵列数据复制到新阵列。但我不想这样做,因为复制是不必要的。我只需要一个
字节[]
-指针,我可以在缓冲区中移动它。像C或C++一样……/P> 下面是一个伪代码示例:

ArrayOriginal = { 0, 1, 2, 3, 4, ... 100 }
ArrayFirstChunk={0,1,2}
(指向原始数组中第一个元素的指针)
ArraySecondChunk={3,4,5}
(指向原始数组中第四个元素的指针)

这可能吗?数据在存储器中只能使用一次


thx

您可以尝试使用
unsafe
获取指向数组的指针。否则,将数组的一部分复制到另一个数组是一种有效的方法。如果发送小块数据,您可以重用小数组实例,并将其留给垃圾收集,以释放数组中的内存。

您不能说是否可以更改API。我想不会,但如果可以,总是会有
IEnumerable
-所以返回

myarray.Skip(4).Take(4); 

etc

您可以创建包含偏移量和长度的数组。这样,您可以使用阵列的子阵列。但它不是数组。

当您将数组作为参数传递时,只传递指向该数组的指针阵列在内存中只存储一次。 所以,我认为你不需要分成小块。 如果你想把它分块处理,我建议你只读取所需的元素,首先从0到2,然后从3到5,等等


希望对您有所帮助

处理数组内数据的常用方法只是指定选定的偏移量和计数,例如:

// {0, ..., 100}
byte[] data = Enumerable.Range(0, 101).Select(i => (byte)i).ToArray();
Write(data, 0, 3);
Write(data, 3, 3);
...
static void Write(byte[] buffer, int offset, int count)
{
    for(int i = offset ; i < offset + count; i++)
        Console.WriteLine(buffer[i]);
    Console.WriteLine();
}

你可以封装一个缓冲区、偏移量和计数,但它不会是一个数组-可能不是很有帮助。

+1很好的答案:)框架中有一个ArraySegment类,但它使用得不多,而且这个方法非常好。你可以在Linq链的末尾再次调用ToArray(),但这将创建一个copyok yes with ToArray()它可以工作,但是数据是用这个命令复制的吗?是的ToArray将使用过滤的元素创建一个新数组。。您确定复制/创建阵列对您来说确实是一个性能问题吗?你分析过这个吗?没有,我没有做过性能测试,但我想用这个技术发送非常大的文件,因为我来自嵌入式世界,所以我认为必须有一个解决方案,只指向数组的一个子集。非常感谢“但我不想这样做,因为复制是不必要的。”您是否已将此视为性能问题,或者是否过早地进行了优化?:)我认为问题的要点是他无法更改API或其行为-因此无法返回数组和“偏移量”等,如果是这样的话,API可能期望一个大小作为参数,并且他可以在一次调用中读取整个数组。过去我通过编写一个“ArrayIterator”对象实现了类似的功能,该对象使用偏移量构造,该偏移量的长度包装对原始数组的访问。有效,但确实需要改变API。这只是一个可怕的建议。在这种情况下,没有理由使用不安全代码。我认为没有理由分割数组,而且我几乎不会调用Buffer.BlockCopyeffective@RamhoundOP已(评论)声明API将只接受
字节[]
,如果OP希望将其发送成小块,则重新使用并重写(通过
区块复制
)缓冲区可能是留给OP的唯一方法。不管是否有效,都需要复制。我认为这真的没有帮助,因为我必须给api调用一个字节[]。无论如何thx@fpdragonk然后看看我对Phill回答的评论,就像MattDavey在上面所说的,这基本上就是ArraySegment所做的。因此,不需要创建“FakeArray”-但您完全正确,它仍然不是数组类型。
fixed(byte* ptr = data)
{
    Write(ptr, 3);
    Write(ptr + 3, 3);
}
...
static unsafe void Write(byte* ptr, int count)
{
    for (int i = 0; i < count; i++)
        Console.WriteLine(ptr[i]);
    Console.WriteLine();
}