Templates casten.
-
daran hatte ich auch schon gedacht, doch das ist nicht so schön zum vererben und ich muss das für jeden datentypen machen
Dabei benutz ich dafür nur Nummerische-Datentypen.
-
und ein einfaches
public point<Int32> ToInt32 () { return (new point<Int32> ((Int32)x_, (Int32)y_)); }
geht auch nicht, da x_ und y_ ja zum Typ T gehören und daher nicht gecastet werden dürfen laut compiler.
-
Hi,
was Du vorhast, geht einfach nicht in C# (oder VB.NET). Daher predige ich ja auch die ganze Zeit, dass die .NET-Generics fehlkonzipiert sind. An Deiner Stelle würde ich mir eine statische 'Convert'-Funktion für die Klasse schreiben, welche per Überladung korrekte Konvertierungen auflöst. Also z.B.:
public static Point<int> Convert(Point<float> p) {/* … */ }
Und noch ein Wort zu Deinem Code: Deine Implementierung für 'Equals' würde ich anders machen und das .NET-Idiom korrekt implementieren. Dadurch sparst Du Dir Tiparebeit und gehst auf Nummer Sicher, dass das Verhalten dasselbe ist, was .NET verlangt. Wie das allgemein geht, habe ich in diesem Forenbeitrag zusammengefasst. Allerdings ist hier die IEquatable-Schnittstelle nicht berücksichtigt.
Außerdem solltest Du auf jeden Fall 'GetHashCode' implementieren. Dafür solltest Du auch ne Warnung vom Compiler erhalten.
-
Nachtrag: Das mit dem 'Convert' klappt natürlich auch nicht direkt. Ein Weg wäre es, über Serialisierung bzw. ToString/Parse zu gehen.
/EDIT: Alles Schwachsinn. Klappt wunderbar.
-
Noch eine Bemerkung: Wieso implementierst Du 'ICloneable'? Deine Struct enthält doch wahrscheinlich eh nur Wertetypen, da reicht die normale Zuweisung aus. Ich würde daher eher vorschlagen, dein Typenparameter 'T' einzuschränken. Außerdem solltest Du Dir überlegen, ob 'T' nicht ebenfalls 'IEquatable<>' implementieren sollte:
struct Point<T> : IEquatable<Point<T>> where T : struct, IEquatable<T>
-
Nochmal zur Implementierung der Gleichheit:
ich habe dafür mal ein Snippet mit dem Kürzel "equality" geschrieben, welches die Implementierung der Schnittstelle für einen vornimmt. Bei Interesse hier herunterladen:
-
C#'ler schrieb:
und ein einfaches
public point<Int32> ToInt32 () { return (new point<Int32> ((Int32)x_, (Int32)y_)); }
geht auch nicht, da x_ und y_ ja zum Typ T gehören und daher nicht gecastet werden dürfen laut compiler.
Hallo,
gib einfach an, dass der Typ T IConvertible implementieren muss und verwend dann statt dem Cast "Convert.ToInt32(x);". Das ganze kann man dann denke ich aber auch schon etwas genereller umsetzen und zwar wie folgt (Ich habe es jetzt aber nicht getestet):
// ... public struct Point<T> : IEquatable<Point<T>> where T : IEquatable<T>, IConvertible<T> { private T x; private T y; // ... public Point<U> ConvertTo<U>() { return new Point<U>( Convert.ChangeType(x, typeof(U)) as U, Convert.ChangeType(y, typeof(U)) as U ); } }
Aufzurufen wäre es eben dann folgendermaßen:
Point<float> point = /* ... */; Point<int> intPoint = point.ConvertTo<int>();
grüße
-
Hi Konrad Rudolph und dssdfsdasd
Dein Denkanstoß hat auf anhieb erste sahne Funktioniert, doch der von dssdfsdasd empfinde ich persönlich als hmn "Ansprechender", sorry. Aber dafür hast du viel viel Feedback gegeben wofür ich dir danke
Leider muss ich sagen wenn ich deinen, dssdfsdasd, code nehme bekomme ich folgende 2 Fehler:
Error 1 The type 'U' must be convertible to 'System.IEquatable<U>' in order to use it as parameter 'T' in the generic type or method 'datastructures.point<T>' Error 2 The type 'U' must be convertible to 'System.IConvertible' in order to use it as parameter 'T' in the generic type or method 'datastructures.point<T>'
Und das alles beim Methodenkopf und nicht im Methodenrumpf:
public point<U> ConvertTo<U> ()
Hast du bzw. ihr dort eine Idee, woran das liegen kann? Wie kann ich denn U für die Funktion auf System.IEquatable<U> und System.IConvertible ausrichten?
Danke euch beiden schon mal im voraus und sorry das ich mich solang nicht gemeldet habe, war im Legoland mit freundin
-
Ach denkt man grade mal keine 2 Minuten nach, kommt einem schon von selbst die Antwort
public point<U> ConvertTo<U> () where U : IEquatable<U>, IConvertible { return new point<U> ( Convert.ChangeType (x, typeof (U)) as U, Convert.ChangeType (y, typeof (U)) as U ); }
Herrlich wie das geht mit dieser Sprache
Jedoch bekomm ich jetzt probleme mit dem "as":
Error 1 The type parameter 'U' cannot be used with the 'as' operator because it does not have a class type constraint nor a 'class' constraint Error 2 The type parameter 'U' cannot be used with the 'as' operator because it does not have a class type constraint nor a 'class' constraint
-
Hast schon einen normalen Cast propiert?
public point<U> ConvertTo<U> () where U : IEquatable<U>, IConvertible { return new point<U> ( (U) Convert.ChangeType (x, typeof (U)), (U) Convert.ChangeType (y, typeof (U)) ); }
-
Hi,
ich muss leider nochmal mit der Gleichheit nerven. Die von mir geposteten Codesnippets wurde nochmal überarbeitet. Die Gleichheits-Semantik von .NET ist ziemlich pervers und um alle Sonderfälle abzudecken reicht es nicht, wenn Klassen und Strukturen denselben Code verwenden.
Die aktuelle Version des Pakets stellt daher unterschiedliche Versionen für Klassen (Shortcut "cequals") und Strukturen ("sequals") bereit. Ich empfehle übrigens, diese Snippets tatsächlich zu benutzen, wenn man die Gleichheit implementieren möchte. Es ist nämlich in .NET leider alles andere als einfach, die Semantik korrekt zu implementieren und wenn man Flüchtigkeitsfehler vermeiden möchte, hilft eine fertige Implementierung ungemein. Für diese Snippets habe ich Unit Tests gemacht, die so ziemlich alle Spezialfälle abdecken, unter anderem auch Vererbung (nur für Klassen relevant).
Hier nochmal der Link: http://madrat.net/coding/dotnet/snippets/equatable.vsi
-
Danke euch beiden!
Ich finde das ist mal ein Thread für die FAQ, die ja (leider) sehr mager ist.