不安全的通用:T[] 和 T[] - C# 7.3+

Generic for unsafe: T[,] and T[,,] - C# 7.3+

我 运行 c# 7.3 所以请不要评论 'this will never work'

我有 2 个 类 具有通用接口: Image2D 和 Image3D 以及通用接口图像

public interface IImage<T, S> where T : unmanaged {
  long Length { get; }
  S Data { get; }
  T GetMaxTypeValue();
  T GetMinTypeValue(); 
}

public abstract class I2D<T> : IImage<T, T[,]> where T : unmanaged {
    public int LengthX { get; }
    public int LengthY { get; }

    public T[,] Data { get; }
    ...
}


public abstract class I3D<T> : IImage<T, T[,,]> where T : unmanaged {
    public int LengthX { get; }
    public int LengthY { get; }
    public int LengthZ { get; }

    public T[,,] Data { get; }
    ....
}

我现在想做什么:无论输入是 I3D 还是 I2D 类型,我都需要对数据数组进行不安全访问...

public static unsafe T Smth<T, S>(IImage<T, S> image) where T : unmanaged where S : unmanaged {
    var data = image.Data;

    fixed (T* pData = data) {
        do someting
    }
    return ...
}

这当然行不通:'Can not convert initializer type S to type T*' 这很有道理……但是我怎样才能得到数组的数据类型呢?有没有更好的办法解决这个问题?

我想知道这里的诀窍是不是 S Data { get; },有(作为 Data,或作为不同的 属性):ref T Data {get;}.

假设你有底层数组,你应该能够使用所有的零来获得这个引用;所以对于 2D 情况:

public ref T Data => ref arr[0, 0];
T[,] arr;

对于 3D 案例:

public ref T Data => ref arr[0, 0, 0];
T[,,] arr;

现在您可以使用:

ref var data = ref image.Data;
fixed (T* pData = &data)
{

}

虽然坦率地说我怀疑你也可以做你需要的一切 没有 unsafe - 特别是通过 MemoryMarshalUnsafe (nuget)