C# Klasse verhält sich merkwürdig



  • Hallo Community,

    ich habe folgende C# Klasse:

    class Matrix
        {
    
            private static double[,] TheMatrix;
            private static int rows, columns;
    
            public  Matrix(int loc_rows, int loc_columns)
            {
                rows = loc_rows;
                columns = loc_columns;
                TheMatrix = new double[rows, columns];
          
            }
    
            public void SetMatrixValue(int loc_rows, int loc_columns, double value) {
                TheMatrix[loc_rows, loc_columns] = value; 
            }
    
    
            public double GetMatrixValue(int loc_rows, int loc_columns)
            {
                return TheMatrix[loc_rows, loc_columns];
            }
    
    }
    
    

    Wenn ich mehrere dieser Klassen initialisiere – etwa so

    
    	    Matrix A = new Matrix(3, 3);
                Matrix B = new Matrix(3, 3);
                Matrix C = new Matrix(3, 3);
    
                A.SetMatrixValue(1, 1, 2);
                B.SetMatrixValue(1, 1, 13);
    
    

    , dann liefert A.GetMatrixValue(1,1) den Wert 13 . Warum wurde nicht der Wert 2 geliefert ?


  • Global Moderator |  Mod

    Was denkst du, was das Schlüsselwort static bedeutet?



  • Vielen Dank für den Hinweis - ABER! wenn ich jetzt zum Beispiel eine Operatorfunktion dieser Form

    public static Matrix operator +(Matrix A, Matrix B)
            {
                int count_c,count_r;
                Matrix result = new Matrix(rows, columns);
                for(count_r = 0; count_r < rows; count_r++){
                     for(count_c = 0; count_c < columns; count_c++){
                         result[count_r,count_c] = A[count_r,count_c] + B[count_r,count_c];
                     }
                }
                return result;
            }
         
    

    hinzufügen, muss ich "TheMatrix" als static deklarieren, da es andernfalls eine Fehlermeldung vom Typ: CS0120 gibt.
    Kannst Du bitte auch mitteilen, wie man dieses Problem lösen könnte ?



  • Warum musst du die Klasse "static" definieren, nur weil der Operator "static" ist?

    Zeig doch am besten mal die gesamte Fehlermeldung, die kommt, wenn du die Klasse nicht static machst.
    Und zeig mal die gesamte Klasse "Matrix", falls nicht zu groß, einschließlich aller Operatoren usw.



  • Mir scheint der eigentliche Hinweis -- mal zu überlegen, was static noch macht außer Fehlermeldungen generieren -- wurde ignoriert.


  • Global Moderator |  Mod

    @bashar sagte in C# Klasse verhält sich merkwürdig:

    Mir scheint der eigentliche Hinweis -- mal zu überlegen, was static noch macht außer Fehlermeldungen generieren -- wurde ignoriert.

    Aber all die coolen Codes aus dem Internet benutzen static! Das muss doch besser sein!



  • Gut – ich mache meine Hausaufgaben
    static:
    Die Variable oder Methode gehört zu einer Klasse. Das heißt, es gibt diese Variable oder Methode nur einmal pro Klasse und kann über klassenname.methodnname() oder klassenname.variablenname genutzt werden. (https://www.fachinformatiker.de/topic/155561-c-was-macht-static/)

    Trotzdem hilft mir das nicht wirklich weiter - ich verstehe nämlich nicht, warum in allen "Matrix" Klassen dann immer dasselbe steht , wenn ich das intern speichernde Objekt (z.B. double array) als static deklariere - ist das ein BUG von C# oder wenn nicht - welchen Nutzen soll das haben ?

    Mein eigentliches Problem ist aber eine Klasse "Matrix" von C++/Cli nach C# zu portieren - vielleicht könnt Ihr mir ja sagen, wie ich folgenden C++/Cli Code (ist jetzt die Division durch einen Skalar - aber auch hier muss ich eine ResultMatrix anlegen) dann am besten nach C# portieren könnte ( in der C++/cli Klasse ist allerdings nichts als static deklariert).

    
            ComplexMatrix^operator /(double second)
            {
                int count_first_rows, count_first_cols;
                ComplexMatrix^ResultMatrix = gcnew ComplexMatrix(this->_rows, this-> _cols);
    
                for (count_first_cols = 0; count_first_cols < this->_cols; count_first_cols++)
                {
                    for (count_first_rows = 0; count_first_rows < this->_rows; count_first_rows++)
                    {
    
                        ResultMatrix[count_first_rows, count_first_cols] = gcnew complex(this[count_first_rows, count_first_cols]->GetReal() / second, this[count_first_rows, count_first_cols]->GetImag() / second);
    
    
                    }
                }
                return ResultMatrix;
            }
    
    
    

    PS: complex ist ein Object, mit dem eine komplexe Zahl ebenfalls als Klasse definiert wird (da stehen dann 2 double Zahlen drin - ebenfalls != static) - die C# Version braucht aber nicht komplex zu sein - daher einfach ein double Array,



  • @7x7-7 Die nächste Hausaufgabe ist, den Unterschied zwischen Klasse und Objekt/Instanz herauszufinden. Ich denke da liegt dein Verständnisproblem.



  • OK ich habe meine Hausaufgaben nochmal angeschaut und dann dass hier gefunden:
    https://blogs.msdn.microsoft.com/ericlippert/2007/05/14/why-are-overloaded-operators-always-static-in-c/

    Wie es aussieht kann ich keine nicht statischen Operatoren in c# deklarieren d.h. C# Operatoren taugen nur für Operationen in denen nichts zwischengespeichert werden muss.



  • @7x7-7 sagte in C# Klasse verhält sich merkwürdig:

    Wie es aussieht kann ich keine nicht statischen Operatoren in c# deklarieren

    Ja, und?

    @it0101 sagte in C# Klasse verhält sich merkwürdig:

    Warum musst du die Klasse "static" definieren, nur weil der Operator "static" ist?



  • Hier kann man sich anschauen, wie mein Problem professionel gelöst wurde (https://www.codeproject.com/Articles/19032/C-Matrix-Library)
    Falls jemand dasselbe Problem hat und aus welchen Gründen auch immer lieber doch eine eigene Matrix-Klasse schreiben möchte hier meine Interpretation dessen was in dem oben genannten Library realisiert wurde:

      public static Matrix operator +(Matrix A, Matrix B)
            {
               
                int count_c,count_r;
                Matrix Result = A; // workaround to avoid a static definition 
                for(count_r = 0; count_r < A.rows; count_r++){
                  for(count_c = 0; count_c < A.columns; count_c++){
                         Result[count_r,count_c] = A[count_r,count_c] + B[count_r,count_c];
                     }
                }
             
                return Result;
            }
    


  • Du kannst doch einfach eine neue Instanz der Matrix als Result erstellen und zurück liefern? Es gibt doch keinerlei Grund dass das nicht gehen würde.

    Dazu brauchst du keine statischen Felder. - Du sollst ja die Werte der beiden übergebenen Matrizen addiert in die neue schreiben. Du brauchst nur einen guten Weg Zeilen und Spalten zu bestimmen. - Lässt sich sicher über geeignete Methoden innerhalb der Klasse Matrix lösen.

    Deine aktuelle Lösung hat das Problem, dass sie nicht funktioniert wenn B mehr Zeilen / Spalten als A hat. Aber auch so funktioniert deine Lösung nicht wirklich. - Auch wenn B < A gibt es Probleme.



  • Hallo nochmal und danke für den letzten Beitrag - ich habe oben genanntes Library genauer angeschaut und gefunden, dass in folgender Zeile (mein zweiter Post)

     Matrix result = new Matrix(rows, columns);
    

    nicht die Initialisierung einer neuen Klasse Matrix das Problem verursacht, sondern der Zugriff auf die nicht statischen Member: rows & columns. Wenn man diese Information stattdessen aus einem der Operanden bezieht - etwa:

     Matrix result = new Matrix(A.rows, A.columns); // so wurde es im Library s.o. gemacht
    

    dann funktioniert es auch (möglicherweise war es das was mein Vorposter auch meinte "Du brauchst nur einen guten Weg Zeilen und Spalten zu bestimmen"

    Vielen Dank für die Diskussion



  • Sehr schön,

    dann hast du wenigstens einen saubereren Stand. - Deine erste Lösung hätte nämlich noch ein paar kleine Probleme mit sich gebracht z.B. dass deine Ursprungsmatrix "A" exakt dem "Result" entspräche. So könntest du mit den Ursprungswerten nichts mehr anfangen.

    Behalte daher immer vor Augen, dass Klassen in C# immer Referenz-Typen sind. Eine Änderung auf einem Objekt (auch in gekapselten Funktionen) hat immer zur Folge, dass sich die tatsächliche Referenz also auch die von außen in die Funktion gegebene Instanz ändert.