Laden...

Template Klasse: "Operator "*" kann nicht auf Operanden vom Typ "T" und "T" angewendet werden"

Erstellt von rob_s vor 8 Jahren Letzter Beitrag vor 8 Jahren 4.619 Views
R
rob_s Themenstarter:in
2 Beiträge seit 2015
vor 8 Jahren
Template Klasse: "Operator "*" kann nicht auf Operanden vom Typ "T" und "T" angewendet werden"

Hi! Ich bin neu in c# und stolpere grade hieran:

class MyVector3<T>
{
    public T x { get; set; }
    public T y { get; set; }
    public T z { get; set; }


    public static MyVector3<T> operator *(MyVector3<T> vec1, MyVector3<T> vec2)
    {
        return new MyVector3<T>(vec1.x * vec2.x, vec1.y * vec2.y, vec1.z * vec2.z);
    }
}

Fehlermeldung:
Fehler 37: Der Operator "*" kann nicht auf Operanden vom Typ "T" und "T" angewendet werden.

Ich hab jetzt mit

class MyVector3<T> where T : IComparable, IFormattable, IConvertible, IComparable<T>, IEquatable<T>

alles hingepackt was mir dazu einfällt aber der Fehler ist immernoch da.

2.078 Beiträge seit 2012
vor 8 Jahren

Es gibt diesen Operator für den Typ T nicht.
Den muss Du extra definieren, oder Du verwendest Typen, die ihn bereits haben, z.B. alle Zahlen-Typen.

Du wirst vermutlich nicht um eine Basisklasse für T herum kommen, wo Du dann deinen Operator definierst.
Siehe Überladbare Operatoren

Viel interessanter ist aber die Frage:
Wozu brauchst Du Generics? Es sieht für mich aus, als würdest Du normale Zahlen brauchen, dann nimm doch einfach int, bzw. double?

16.806 Beiträge seit 2008
vor 8 Jahren

Es ist hier nicht ersichtlich, was T ist.
Daher kann der Compiler hier auch keine Multiplikation durchführen.

742 Beiträge seit 2005
vor 8 Jahren

Du kommst bestimmt von C++, dort werden die Templates vom Compiler auch nur als Templates genutzt und nur die konkreten Typen kompiliert, z.B. Vector<float>. In C# werden Generics aber zur Laufzeit aufgelöst und dann muss der Compiler eben die Rahmenbedingungen kennen.

Leider ist heir C# nicht mächtig genug.

EDIT: Wenn du sowas machen willst, würde ich einfach Code Generierung anwenden.

R
rob_s Themenstarter:in
2 Beiträge seit 2015
vor 8 Jahren

Es sieht für mich aus, als würdest Du normale Zahlen brauchen, dann nimm doch einfach int, bzw. double?

tja ich wollte beides. einen Int-Vector und einen double-Vector.

*ächz* in c++ hätt ich die Klasse in 2 minuten abgetippt...

Es ist hier nicht ersichtlich, was T ist.

Deshalb das

where
742 Beiträge seit 2005
vor 8 Jahren

Das where (nennt sich constraints) würde grundsätzlich gehen, du könntest zum Beispiel Formulieren, dass alle T's bestimmte mathematische Operationen unterstützen müssen, ABER...

  1. Es gibt keine passendes Interface
  2. Interfaces können keine Operatoren haben

Beispielsweise:


interface ISupportPlus<T>
{
   T Add(T other);
}

class Vector<T> where T : ISupportsPlus<T>
{
    T x, y, z;

    Vector<T> Add(Vector<T> other)
    {
        return new Vector<T>(x.Add(other.x), ...);
    }
}

Aber wie gesagt: Es geht einfach nicht 😦

1.346 Beiträge seit 2008
vor 8 Jahren

Entsprechende generic constraints sind aber aktuell im Gespräch um das in kommenden C# Versionen zu unterstützen. Aktuell geht das leider nicht nicht.

16.806 Beiträge seit 2008
vor 8 Jahren

Also "es geht nicht" ist mal pauschal falsch 😃
Es geht, aber nur, wenn man auf Typsicherheit verzichtet und dynamic verwendet.

F
10.010 Beiträge seit 2004
vor 8 Jahren

@malignate:

In C# werden Generics aber zur Laufzeit aufgelöst und dann muss der Compiler eben die Rahmenbedingungen kennen.

Stimmt nicht, denn dann würdest du nicht einen Compilerfehler bei dem Konstrukt erhalten sondern eine Exception zur Laufzeit.

Aber es wird nicht beim Compilieren des konkreten T geprüft, sondern beim compilieren der Generischen Implementierung.

742 Beiträge seit 2005
vor 8 Jahren

Vielleicht sind die Begriffe falsch, aber es passiert beides: Der Generic wird Type wird vom Compiler erzeugt und Informationen über alle Typparameter inklusive Constraints hinterlegt.

Deshalb ist es auch nicht möglich mit Reflection ungültigen Typen für die Parameter zu erzeugen.

In C++ sind das einfach zwei verschiedene Klassen.

I
1.739 Beiträge seit 2005
vor 8 Jahren

Law of Demeter.
Operatoren können nur für konkrete Klassen/Interfaces erzeugt werden.

742 Beiträge seit 2005
vor 8 Jahren

Das ist einfache eine Design-Entscheidung gewesen: Why are overloaded operators always static in C#?

Den Zusammenhang mit Law of Demeter sehe ich jetzt nicht.

I
1.739 Beiträge seit 2005
vor 8 Jahren

Law of Demeter: rede nicht mit Fremden.
Generische Klassen/ Interfaces implementieren nicht unbedingt die verlangten/benutzten Operatoren nach Definition,dieImplementation kann sehr willkürlich sein. Keine Garantie, kein Vertrag.

742 Beiträge seit 2005
vor 8 Jahren

Ich kapier es immer noch nicht. Operatoren sind in erster Linie nur syntaktischer Zucker. Allerdings sind die aus Gründen der Symmetrie statisch (siehe Link) und können deshalb nicht Teil von Interfaces sein. Law of Demeter sagt ja auch nicht: Rede mit Niemandem

I
1.739 Beiträge seit 2005
vor 8 Jahren

Mein Posting war auch sprachununabhängig.
Operatoren sind Funktionen.
Die Ausführung solcher, liefert zwar ein Ergebnis zurück....
Deshalb kann ein Operator kein Bestandteil einer generischen Klasse oder eines Interfaces sein.
Vermute mal, ich habe mich zuvor unverständlich ausgerdrückt.