Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

Template Klasse: "Operator "*" kann nicht auf Operanden vom Typ "T" und "T" angewendet werden"
rob_s
myCSharp.de - Member



Dabei seit:
Beiträge: 2

Themenstarter:

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

beantworten | zitieren | melden

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);
    }
}
Fehler
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.
private Nachricht | Beiträge des Benutzers
Palladin007
myCSharp.de - Member

Avatar #avatar-4140.png


Dabei seit:
Beiträge: 1.782
Herkunft: Düsseldorf

beantworten | zitieren | melden

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?
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Palladin007 am .
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 15.844

beantworten | zitieren | melden

Es ist hier nicht ersichtlich, was T ist.
Daher kann der Compiler hier auch keine Multiplikation durchführen.
private Nachricht | Beiträge des Benutzers
malignate
myCSharp.de - Member

Avatar #avatar-3206.png


Dabei seit:
Beiträge: 742

beantworten | zitieren | melden

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.
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von malignate am .
private Nachricht | Beiträge des Benutzers
rob_s
myCSharp.de - Member



Dabei seit:
Beiträge: 2

Themenstarter:

beantworten | zitieren | melden

Zitat
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...
Zitat
Es ist hier nicht ersichtlich, was T ist.
Deshalb das

where
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von rob_s am .
private Nachricht | Beiträge des Benutzers
malignate
myCSharp.de - Member

Avatar #avatar-3206.png


Dabei seit:
Beiträge: 742

beantworten | zitieren | melden

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 :(
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von malignate am .
private Nachricht | Beiträge des Benutzers
pdelvo
myCSharp.de - Member

Avatar #avatar-3354.png


Dabei seit:
Beiträge: 1.346

beantworten | zitieren | melden

Entsprechende generic constraints sind aber aktuell im Gespräch um das in kommenden C# Versionen zu unterstützen. Aktuell geht das leider nicht nicht.
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 15.844

beantworten | zitieren | melden

Also "es geht nicht" ist mal pauschal falsch :-)
Es geht, aber nur, wenn man auf Typsicherheit verzichtet und dynamic verwendet.
private Nachricht | Beiträge des Benutzers
FZelle
myCSharp.de - Experte



Dabei seit:
Beiträge: 9.976

beantworten | zitieren | melden

@malignate:
Zitat
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.
private Nachricht | Beiträge des Benutzers
malignate
myCSharp.de - Member

Avatar #avatar-3206.png


Dabei seit:
Beiträge: 742

beantworten | zitieren | melden

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.
private Nachricht | Beiträge des Benutzers
ikaros
myCSharp.de - Member



Dabei seit:
Beiträge: 1.739

beantworten | zitieren | melden

Law of Demeter.
Operatoren können nur für konkrete Klassen/Interfaces erzeugt werden.
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von ikaros am .
private Nachricht | Beiträge des Benutzers
malignate
myCSharp.de - Member

Avatar #avatar-3206.png


Dabei seit:
Beiträge: 742

beantworten | zitieren | melden

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.
private Nachricht | Beiträge des Benutzers
ikaros
myCSharp.de - Member



Dabei seit:
Beiträge: 1.739

beantworten | zitieren | melden

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.
private Nachricht | Beiträge des Benutzers
malignate
myCSharp.de - Member

Avatar #avatar-3206.png


Dabei seit:
Beiträge: 742

beantworten | zitieren | melden

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
private Nachricht | Beiträge des Benutzers
ikaros
myCSharp.de - Member



Dabei seit:
Beiträge: 1.739

beantworten | zitieren | melden

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.
private Nachricht | Beiträge des Benutzers