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.
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?
NuGet Packages im Code auslesen
lock Alternative für async/await
Beim CleanCode zählen nicht die Regeln, sondern dass wir uns mit diesen Regeln befassen, selbst wenn wir sie nicht befolgen - hoffentlich nach reiflichen Überlegungen.
Es ist hier nicht ersichtlich, was T ist.
Daher kann der Compiler hier auch keine Multiplikation durchführen.
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code
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.
ImageTools for Silverlight: http://imagetools.codeplex.com | http://www.silverdiagram.net | http://www.cleancodedeveloper.de b:::
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
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...
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 😦
ImageTools for Silverlight: http://imagetools.codeplex.com | http://www.silverdiagram.net | http://www.cleancodedeveloper.de b:::
Entsprechende generic constraints sind aber aktuell im Gespräch um das in kommenden C# Versionen zu unterstützen. Aktuell geht das leider nicht nicht.
Also "es geht nicht" ist mal pauschal falsch 😃
Es geht, aber nur, wenn man auf Typsicherheit verzichtet und dynamic
verwendet.
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code
@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.
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.
ImageTools for Silverlight: http://imagetools.codeplex.com | http://www.silverdiagram.net | http://www.cleancodedeveloper.de b:::
Law of Demeter.
Operatoren können nur für konkrete Klassen/Interfaces erzeugt werden.
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.
ImageTools for Silverlight: http://imagetools.codeplex.com | http://www.silverdiagram.net | http://www.cleancodedeveloper.de b:::
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.
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
ImageTools for Silverlight: http://imagetools.codeplex.com | http://www.silverdiagram.net | http://www.cleancodedeveloper.de b:::
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.