Frage von okarin, 70

C# Matrix Klasse schreiben?

Hallo,

ich hab mir gestern eine kleine Matrix-Klasse in c# geschrieben. Dabei speichere ich die Matrix in einem 2 dimensionalen Array. Mittels indexer hab ich es auch hinbekommen das man direkt über die Klasse Werte in dem Array abfragen und ändern kann. Mein Problem ist das ich um bestimmte Anfragen auf das Array zu tätigen ja immer noch direkten Zugriff über einen getter brauch. Das ist meiner Meinung aber ziemlich unschön, ich fände es schöner wenn ich sozusagen von einem 2-dimensionalen Array Erbe damit dann die Klasse die Eigenschaften und Funktionen des Arrays übernimmt. Ich weiß, dass das so leider nicht möglich ist aber vielleicht hat ja jmd. eine Idee wie man sowas besser gestalten könnte.

Vielen Dank für alle Antworten

Antwort
von CrystalixXx, 45

Natürlich kannst du deine eigene Klasse als Array/List/Collection erstellen. Entweder du erbst von einer solchen Klasse oder du implementierst entsprechende Schnittstellen und programmierst die Methoden selbst.

Du musst die Daten ja nicht so nach außen geben, wie du sie intern speicherst.

Vielleicht erklärst du aber nochmal genauer, was du eigentlich willst. Eventuell mit Beispielcode.

Kommentar von okarin ,

Ja aber kann ich eine Vererbung von Array dann auch so einschränken das ich nur 2-dimensionale Arrays erstellen darf?

Für den Beispielcode siehe Antwort von EightSix.

Kommentar von okarin ,

Oh warte mein Gott bin ich blöd es reicht einfach wenn ich von Array erbe und das ganze dann in dem Konstruktor einschränke so dass ich nur zwei dimensionale arrays erstellen kann oder?

Kommentar von CrystalixXx ,

Du kannst keine Klasse direkt von Array ableiten; das ist dem Compiler vorbehalten. Du kannst aber von IList implementieren.

Ich würde die Daten der Matrix zwar als 2-dim. Array speichern, aber über eine Column- und Row-Eigenschaft (jeweils als 1-dim. Array) nach außen geben, um den Zugriff auf die einzelnen Elemente zu erhalten. Das macht die Verwendung der Matrix einfacher und transparenter, wie ich finde.

Schau dir mal die Interfaces ICollection, IList, IEnumerable etc. an. An sich würde ich davon abraten von Listen zu erben oder Listen-Schnittstellen zu implementieren, weil du dir damit Methoden einhandelst, die du gar nicht brauchst. Erstelle die notwendigen Methoden selbst.

Kommentar von okarin ,

Also eher so wie beim DataGridView?

Kommentar von CrystalixXx ,

Ja.

Antwort
von Mikkey, 23

Du meinst vermutlich, dass so eine Funktion "GetLength(int dimension)" z.B. in Deiner Klasse in das Array hinduchgeschleift werden muss.

int GetLength(int Dimension) {return myArray.GetLength(Dimension);}

Eine schöne Lösung habe ich dafür aber auch nicht, Array sind da aber eine Ausnahme, denn mit Collections, Dictionaries etc kann man so etwas ohne Weiteres machen.

Antwort
von EightSix, 50

Mach mal ein Beispiel was du meinst.

Kommentar von okarin ,

Ich schick jetzt einfach mal den Code:

class Matrix
{
#region Fields
private double[,] matrixArray;
#endregion Fields

#region Properties
public double this[int i, int j]
{
get
{
return this.matrixArray[i, j];
}

set
{
this.matrixArray[i, j] = value;
}
}

public double[,] MatrixArray
{
get
{
return matrixArray;
}
}

#endregion Properties

#region Constructor
public Matrix()
{
this.matrixArray = null;
}

public Matrix(int heigth, int width)
{
this.matrixArray = new double[heigth, width];
}

public Matrix(double[,] m)
{
this.matrixArray = m;
}
#endregion Constructor

#region Operatoren

public static Matrix operator+(Matrix a, Matrix b)
{
// Matritzen müssen gleiche größen haben
if (a.MatrixArray.GetLength(0) != b.MatrixArray.GetLength(0) || a.MatrixArray.GetLength(1) != b.MatrixArray.GetLength(1))
{
throw new MatrixFalseFormatException();
}

Matrix m = new Matrix(a.MatrixArray.GetLength(0), a.MatrixArray.GetLength(1));

// Jedes Element addieren
for(int i = 0; i < m.MatrixArray.GetLength(0); i++)
{
for(int j = 0; j < m.MatrixArray.GetLength(1); j++)
{
m[i, j] = a[i, j] + b[i, j];
}
}

return m;
}

public static Matrix operator-(Matrix a, Matrix b)
{
// Matritzen müssen gleiche größen haben
if (a.MatrixArray.GetLength(0) != b.MatrixArray.GetLength(0) || a.MatrixArray.GetLength(1) != b.MatrixArray.GetLength(1))
{
throw new MatrixFalseFormatException();
}

Matrix m = new Matrix(a.MatrixArray.GetLength(0), a.MatrixArray.GetLength(1));

// Jedes Element subtraieren
for (int i = 0; i < m.MatrixArray.GetLength(0); i++)
{
for (int j = 0; j < m.MatrixArray.GetLength(1); j++)
{
m[i, j] = a[i, j] - b[i, j];
}
}

return m;
}

public static Matrix operator*(Matrix a, Matrix b)
{
if (a.MatrixArray.GetLength(1) != b.MatrixArray.GetLength(0))
{
throw new MatrixFalseFormatException();
}

Matrix m = new Matrix(a.MatrixArray.GetLength(0), b.MatrixArray.GetLength(1));

// Zeilen mit Spalten multiplizieren
for (int i = 0; i < m.MatrixArray.GetLength(0); i++)
{
for (int j = 0; j < m.MatrixArray.GetLength(1); j++)
{
for (int k = 0; k < a.MatrixArray.GetLength(1); k++)
{
m[i, j] += a[i, k] * b[k, j];
}
}
}

return m;
}

public static Matrix operator^(Matrix a, uint b)
{
for (int i = 0; i < b; i++)
{
a *= a;
}

return a;
}
#endregion Operatoren
}

Wenn ich damit jetzt beispielsweise die größe der Matrix abfragen will muss ich auf die Property MatrixArray zugreifen um dann auf GetLength() zuzugreifen. Jetzt wäre es natürlich schön wenn GetLength() direkt zu meiner Klasse Matrix gehört. Ich könnte jetzt natürlich für alle Funktionen die ich benutzen will eine extra Funktion in Matrix anlegen was dann aber einfach nicht schön ist. Deshalb hab ich an sowas wie Vererbung gedacht was aber auch nicht möglich ist.

Kommentar von EightSix ,

Würde an deiner Stelle eine Klasse schreiben für ein Matrix-Element und dann eine Klasse machen die von einer generischen, enumerierbaren Klasse erbt.

Keine passende Antwort gefunden?

Fragen Sie die Community