C#如何向接收数组参数的函数传入值类型数组的引用切片
解决方案
C#目前有两类可落地的实现方案,适配不同的使用场景:
方案1:全版本兼容的临时数组回拷方案
不需要开启不安全代码,兼容所有.NET Framework/.NET版本,是标准实现方式:
- 从原数组切片位置拷贝对应数量的
Point/PointF到临时数组 - 将临时数组传入
Matrix.TransformPoints执行变换 - 把变换后的临时数组元素回写到原数组的对应切片位置
如果切片操作很频繁,可以复用固定大小的临时数组,避免反复分配内存带来的GC开销。
示例代码如下:
public static void TransformPointsSlice(this Matrix matrix, Point[] source, int startIndex, int length) { // 可复用全局临时数组代替每次new,进一步优化性能 Point[] temp = new Point[length]; Array.Copy(source, startIndex, temp, 0, length); matrix.TransformPoints(temp); Array.Copy(temp, 0, source, startIndex, length); } // 调用示例:处理索引2到3的切片 matrix.TransformPointsSlice(points, 2, 2);
方案2:零拷贝高性能实现
因为官方Matrix.TransformPoints没有提供Span/指针重载,要实现完全无拷贝的操作,可以直接基于矩阵变换的数学逻辑实现自定义方法,性能最优,实现逻辑也非常简单:
public static void TransformPointsSpan(this Matrix matrix, Span<Point> points) { // 获取矩阵的六个元素:M11, M12, M21, M22, OffsetX, OffsetY float m11 = matrix.Elements[0], m12 = matrix.Elements[1]; float m21 = matrix.Elements[2], m22 = matrix.Elements[3]; float dx = matrix.Elements[4], dy = matrix.Elements[5]; for (int i = 0; i < points.Length; i++) { int x = points[i].X, y = points[i].Y; points[i].X = (int)(x * m11 + y * m21 + dx); points[i].Y = (int)(x * m12 + y * m22 + dy); } } // 调用示例:零拷贝直接修改原数组切片 matrix.TransformPointsSpan(points.AsSpan(2, 2));
如果项目允许开启不安全代码,也可以用和C语言完全一致的指针偏移逻辑操作内存,配合栈内存分配可以大幅降低小切片场景的性能开销。
内容的提问来源于stack exchange,提问作者xZise
相关产品推荐
相关产品推荐

