Laden...

Probleme beim überladen von Operatoren in generischen Klassen

Erstellt von Gogonfa vor 15 Jahren Letzter Beitrag vor 15 Jahren 2.540 Views
G
Gogonfa Themenstarter:in
11 Beiträge seit 2008
vor 15 Jahren
Probleme beim überladen von Operatoren in generischen Klassen

Hallo Leute,

ich versuche in einer generischen Klasse den Operator + zu überladen....leider bisher ohne viel Erfolg!!! In einem älteren Thread hatte schonmal jemand dieses Problem beschrieben (2006) gibt es schon bessere Lösungen für dieses Problem???


public static Matrix<T> operator +(Matrix<T> M1, Matrix<T> M2)
        {
            int i_M1, i_M2, k_M1, k_M2;

            i_M1 =M1._MatrixElements .GetLength(0);
            i_M2 =M2._MatrixElements .GetLength(0);
            k_M1 =M1._MatrixElements .GetLength(1);
            k_M2 =M2._MatrixElements .GetLength(1);

            if ((i_M1 == i_M2) && (k_M1 == k_M2))
            {
                Matrix<T> Summe = new Matrix<T>(M1._MatrixElements.GetLength(0), M1._MatrixElements.GetLength(1));

                for (int i = 0; i <= i_M1; i++)
                {
                    for (int k = 0; k <= k_M1; k++)
                    {
                        Summe[i, k] = M1[i, k] + M2[i, k];
                    }
                }

                return Summe;
            }
            else
            {
                throw new Exception("Matrizen nicht vom selben Typ!");
            }
        }

Dieser Code produziert folgenden Fehler:

Fehler 1 Der Operator "+" kann nicht auf Operanden vom Typ "T" und "T" angewendet werden.

Vielen Dank für Eure Hilfe

grüße
Gogonfa

S
8.746 Beiträge seit 2005
vor 15 Jahren

Kurze Antwort: Geht nicht (direkt) in C#.

http://www.codeproject.com/KB/cs/genericnumerics.aspx

849 Beiträge seit 2006
vor 15 Jahren

Hi Gogonfa

hmm leider kann man T nicht so einschränken wie Du es brauchst..

schön wäre wenn so etwas funktionieren könnte: where T: operator+

Ich nehme an T als abstrakte Klasse zu definieren Fällt aus? Wahrscheinlich willst du da eher nen Int oder Double reinschieben.. richtig?

49.485 Beiträge seit 2005
vor 15 Jahren

Hallo Gogonfa,

In einem älteren Thread hatte schonmal jemand dieses Problem beschrieben (2006) gibt es schon bessere Lösungen für dieses Problem???

wenn du darauf einen Antwort haben willst, solltest du einen Link auf den Thread abgeben.

herbivore

G
Gogonfa Themenstarter:in
11 Beiträge seit 2008
vor 15 Jahren

Hallo herbivore,

link hatte ich vergessen...sorry!!! 8o

Generics und das Überladen von Operatoren

grüße

gogonfa

G
Gogonfa Themenstarter:in
11 Beiträge seit 2008
vor 15 Jahren

Hi unconnected ,

ich möchte eine möglichst allgemeine Klasse für ein Matrix-Objekt entwerfen! Die soll im prinzip mit allen datentypen funzen.....double, float, int und Complex(den habe ich mir schon gemacht)

ich habe ne lösung, die ist aber verdammt langsam!!!


  public class Matrix<T,C> : IDisposable where C: ICalculator<T>,new()
    {

        #region Variablen und Konstanten
        private bool _isDisposed = false;
        private T[,] _MatrixElements;
        protected C _Calculator = new C();
        #endregion

        #region Konstruktor
        /// <summary>
        /// Stellt eine Matrix zur Verfügung
        /// </summary>
        /// <param name="i">Anzahl der Zeilen</param>
        /// <param name="k">Anzahl der Spalten</param>
        public Matrix(int i, int k)
        {
            _MatrixElements = new T[i, k];
        }
        #endregion

        #region Destruktor
        /// <summary>
        /// Destruktor der Matrixklasse
        /// </summary>
        ~Matrix()
        {
            this.Dispose();
        }
        #endregion

        #region Operatoren
      
        #endregion

        #region Methoden
        /// <summary>
        /// Gibt die von Matrix verwendeten Resourcen wieder frei.
        /// </summary>
        public void Dispose()
        {
            if (!_isDisposed)
            {
                _isDisposed = true;
                GC.SuppressFinalize(this);
            }
        }

        public virtual void Add(Matrix<T, C> M)
        {
            int i_M1, i_M2, k_M1, k_M2;

            i_M1 = this._MatrixElements.GetLength(0);
            i_M2 = M._MatrixElements.GetLength(0);
            k_M1 = this._MatrixElements.GetLength(1);
            k_M2 = M._MatrixElements.GetLength(1);

            if ((i_M1 == i_M2) && (k_M1 == k_M2))
            {
                for (int i = 0; i <= i_M1; i++)
                {
                    for (int k = 0; k <= k_M1; k++)
                    {
                        this[i, k] = _Calculator.Add(this[i, k], M[i, k]);
                    }
                }
            }
            else
            {
                throw new Exception("Matrizen nicht vom selben Typ!");
            }
        }
        public virtual void Sub(Matrix<T, C> M)
        {
            int i_M1, i_M2, k_M1, k_M2;

            i_M1 = this._MatrixElements.GetLength(0);
            i_M2 = M._MatrixElements.GetLength(0);
            k_M1 = this._MatrixElements.GetLength(1);
            k_M2 = M._MatrixElements.GetLength(1);

            if ((i_M1 == i_M2) && (k_M1 == k_M2))
            {
                for (int i = 0; i <= i_M1; i++)
                {
                    for (int k = 0; k <= k_M1; k++)
                    {
                        this[i, k] = _Calculator.Sub(this[i, k], M[i, k]);
                    }
                }
            }
            else
            {
                throw new Exception("Matrizen nicht vom selben Typ!");
            }
        }
        public virtual void Mult(Matrix<T, C> M)
        {
            int i_M1, i_M2, k_M1, k_M2;

            i_M1 = this._MatrixElements.GetLength(0);
            i_M2 = M._MatrixElements.GetLength(0);
            k_M1 = this._MatrixElements.GetLength(1);
            k_M2 = M._MatrixElements.GetLength(1);

            if ((i_M1 == k_M2) && (k_M1 == i_M2))
            {
                Matrix<T, C> Produkt = new Matrix<T, C>(i_M1, k_M2);

                for (int i = 0; i <= i_M1; i++)
                {
                    for (int j = 0; j <= k_M2; j++)
                    {
                        for (int k = 0; k <= k_M1; k++)
                        {
                            Produkt[i, j] = _Calculator.Add( Produkt[i, j] , _Calculator.Mul(this[i, k] , M[k, j]));
                        }
                    }
                }
            }
            else
            {
                throw new Exception("Matrizen nicht vom selben Typ!");
            }
        }
       
        #endregion

        #region Eigenschaften
        /// <summary>
        /// Lesen und Schreiben des Wertes für die gewählte Zeile bzw. Spalte
        /// </summary>
        /// <param name="i">Zeile</param>
        /// <param name="k">Spalte</param>
        /// <returns>Gibt den Wert der gewählten Spalte und Zeile zurück.</returns>
        public T this[int i, int k]
        {
            get
            {
                return _MatrixElements[i, k];
            }

            set
            {
                _MatrixElements[i, k] = value;
            }
        }
        #endregion

    }

dazu noch das Interface


 public interface ICalculator<T> 
    {
        T Add(T var1, T var2);
        T Sub(T var1, T var2);
        T Mul(T var1, T var2);
    }

und Klassen zur implementierung der math. Funktionen....


 public class ComplexCalculator : ICalculator<Complex> 
    {

        #region ICalculator<Complex> Members

        public Complex Add(Complex var1, Complex var2)
        {
            return var1 + var2;
        }

        public Complex Sub(Complex var1, Complex var2)
        {
            return var1 - var2;
        }

        public Complex Mul(Complex var1, Complex var2)
        {
            return var1 * var2;
        }

        #endregion
    }
    public class DoubleCalculator : ICalculator<double>
    {

        #region ICalculator<double> Members

        public double Add(double var1, double var2)
        {
            return var1 + var2;
        }

        public double Sub(double var1, double var2)
        {
            return var1 - var2;
        }

        public double Mul(double var1, double var2)
        {
            return var1 * var2;
        }

        #endregion
    }
    public class FloatCalculator : ICalculator<float>
    {

        #region ICalculator<float> Members

        public float Add(float var1, float var2)
        {
            return var1 + var2;
        }

        public float Sub(float var1, float var2)
        {
            return var1 - var2;
        }

        public float Mul(float var1, float var2)
        {
            return var1 * var2;
        }

        #endregion
    }
    public class shortCalculator : ICalculator<short>
    {

        #region ICalculator<short> Members

        public short Add(short var1, short var2)
        {
            return  (short)(var1 + var2);
        }

        public short Sub(short var1, short var2)
        {
            return (short)(var1 - var2);
        }

        public short Mul(short var1, short var2)
        {
            return (short)(var1 * var2);
        }

        #endregion
    }
    public class intCalculator : ICalculator<int>
    {

        #region ICalculator<int> Members

        public int Add(int var1, int var2)
        {
            return var1 + var2;
        }

        public int Sub(int var1, int var2)
        {
            return var1 - var2;
        }

        public int Mul(int var1, int var2)
        {
            return var1 * var2;
        }

        #endregion
    }

das geht....aber Performance ist ganz weit unten im Keller!!!
ich brauche halt ne flexible Matrix-Klasse bei der die Performance was math. Operationen sehr gut sein muss....

grüße

Gogonfa

4.931 Beiträge seit 2008
vor 15 Jahren

Wenn du performante Operationen für große Matrizen benötigst, dann würde ich dies mittels unmanaged Code (z.B. als C-DLL) machen und dann mittels PInvoke (DllImport) einbinden.

S
248 Beiträge seit 2008
vor 15 Jahren

Hallo Gogonfa,

falls du .NET 3.5 verwendest, könntest du dir mal folgende Lib anschauen:
http://www.yoda.arachsys.com/csharp/miscutil/

In dieser gibt es eine Klasse (MiscUtil.Operator<T>) mit der generische Operatoren möglich sind wie zB:


...
T t = Operator<T>.Add(val1, val2);

Spook

G
Gogonfa Themenstarter:in
11 Beiträge seit 2008
vor 15 Jahren

Hi Spook,

sieht ganz interessant aus ...ich schaus mir mal näher an....DANKE!!!!

grüße
Gogonfa