Общее для небезопасных: T [,] и T [,,] - C # 7.3+ - PullRequest
0 голосов
/ 03 июля 2018

Я запускаю c # 7.3, поэтому, пожалуйста, не комментируйте, как «это никогда не сработает»

У меня есть 2 класса с общим интерфейсом: Image2D и Image3D и общий интерфейс Image

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 ...
}

Это, конечно, не работает: «Не удается преобразовать инициализатор типа S в тип T *», что имеет смысл ... Но как я могу получить тип данных массивов? Есть ли лучший способ решить эту проблему?

1 Ответ

0 голосов
/ 03 июля 2018

Интересно, если уловка здесь вместо 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 - особенно через MemoryMarshal и Unsafe ( nuget )

...