Ist es möglich, C # double [,,] Array zu verdoppeln [], ohne eine Kopie zu konvertieren

StackOverflow https://stackoverflow.com/questions/96054

  •  01-07-2019
  •  | 
  •  

Frage

Ich habe großen 3D-Arrays von Zahlen in meiner .NET-Anwendung. Ich brauche sie in eine 1D-Array konvertieren es in einer COM-Bibliothek zu übergeben. Gibt es eine Möglichkeit, das Array zu konvertieren, ohne eine Kopie aller Daten zu machen?

kann ich die Umwandlung wie dies tun, aber dann, die ich zweimal die ammount Speicher ein Problem in meiner Anwendung ist:

  double[] result = new double[input.GetLength(0) * input.GetLength(1) * input.GetLength(2)];
  for (i = 0; i < input.GetLength(0); i++) 
    for (j = 0; j < input.GetLength(1); j++) 
      for (k = 0; k < input.GetLength(2); k++) 
        result[i * input.GetLength(1) * input.GetLength(2) + j * input.GetLength(2) + k)] = input[i,j,l];
  return result;
War es hilfreich?

Lösung

Ich glaube nicht, die Art und Weise C # speichert die Daten im Speicher machen würden möglich die gleiche Art und Weise eine einfache Guss in C würde. Warum nicht einen 1D-Array verwenden, um mit zu beginnen, und vielleicht eine Klasse für den Typen zu machen, so dass Sie es in Ihrem Programm zugreifen können, als ob es ein 3D-Array war?

Andere Tipps

Leider C # Arrays sind nicht in zusammenhängenden Speicher sein garantiert, wie sie in enger-to-the-Metall-Sprachen wie C sind also nicht. Es gibt keine Möglichkeit, doppelt zu konvertieren [,,] [verdoppeln] ohne eine Element-für-Element kopieren.

Betrachten mit einem Proxy (ähnlich Iteratoren / smart-Zeiger in C ++). Leider ist Syntax nicht so sauber wie C ++ als Operator () nicht zur Verfügung, um eine Überlastung und Operator [] ist Single-arg, aber immer noch nahe.

Natürlich ist diese zusätzliche Ebene der Abstraktion erhöht die Komplexität und die Arbeit ihrer eigenen, aber es Ihnen erlauben würde, minimale Änderungen an den bestehenden Code zu machen, die doppelt verwendet [,,] Objekte, während Sie gleichzeitig eine einzelne Doppel verwenden [] Array sowohl für Interop und Ihre in-C # Berechnung.

class Matrix3
{
    // referece-to-element object
    public struct Matrix3Elem{
        private Matrix3Impl impl;
        private uint dim0, dim1, dim2;
        // other constructors
        Matrix3Elem(Matrix3Impl impl_, uint dim0_, uint dim1_, uint dim2_) {
            impl = impl_; dim0 = dim0_; dim1 = dim1_; dim2 = dim2_;
        }
        public double Value{
            get { return impl.GetAt(dim0,dim1,dim2); }
            set { impl.SetAt(dim0, dim1, dim2, value); }
        }
    }

    // implementation object
    internal class Matrix3Impl
    {
        private double[] data;
        uint dsize0, dsize1, dsize2; // dimension sizes
        // .. Resize() 
        public double GetAt(uint dim0, uint dim1, uint dim2) {
            // .. check bounds
            return data[ (dim2 * dsize1 + dim1) * dsize0 + dim0 ];
        }
        public void SetAt(uint dim0, uint dim1, uint dim2, double value) {
            // .. check bounds
            data[ (dim2 * dsize1 + dim1) * dsize0 + dim0 ] = value;
        }
    }

    private Matrix3Impl impl;

    public Matrix3Elem Elem(uint dim0, uint dim1, uint dim2){
        return new Matrix2Elem(dim0, dim1, dim2);
    }
    // .. Resize
    // .. GetLength0(), GetLength1(), GetLength1()
}

Und dann mit dieser Art lesen und schreiben - ‚foo [1,2,3]‘ wird nun als ‚foo.Elem (1,2,3) .Value‘ geschrieben, in beiden Ablesewerte und Schreiben Werte, auf der linken Seite der Zuweisung und Wertausdrücke.

void normalize(Matrix3 m){

    double s = 0;
    for (i = 0; i < input.GetLength0; i++)     
        for (j = 0; j < input.GetLength(1); j++)       
            for (k = 0; k < input.GetLength(2); k++)
    {
        s += m.Elem(i,j,k).Value;
    }
    for (i = 0; i < input.GetLength0; i++)     
        for (j = 0; j < input.GetLength(1); j++)       
            for (k = 0; k < input.GetLength(2); k++)
    {
        m.Elem(i,j,k).Value /= s;
    }
}

Auch hier hinzugefügt Entwicklungskosten, sondern Aktien Daten, Entfernen von Overhead und Kopiervorgänge developtment Kosten zu kopieren. Es ist ein Kompromiss.

Als Abhilfe können Sie eine Klasse machen, die das Array in eindimensionaler Form beibehält (vielleicht sogar in enger Metallform entblößen, so dass Sie es leicht an die COM-Bibliothek passieren können?) Und dann Betreiber überlasten [] auf dieser Klasse macht es verwendbar als ein mehrdimensionales Array in C # -Code.

Ohne Einzelheiten Ihrer COM-Bibliothek zu wissen, würde ich schauen in eine Fassadenklasse in .NET erstellen und zu COM ggf. auszusetzen.
Ihre Fassade würde eine doppelte [,,] und haben einen Indexer, die von [] bis [,,] abbildet.

Edit:. Ich über die Punkte stimmen in den Kommentaren, Lorens Vorschlag ist besser

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top